summaryrefslogtreecommitdiff
path: root/thirdparty
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty')
-rw-r--r--thirdparty/README.md31
-rw-r--r--thirdparty/certs/ca-certificates.crt207
-rw-r--r--thirdparty/enet/godot.cpp64
-rw-r--r--thirdparty/freetype/include/freetype/config/ftoption.h4
-rw-r--r--thirdparty/glad/glad.c1533
-rw-r--r--thirdparty/glad/glad/glad.h87
-rw-r--r--thirdparty/libvpx/third_party/android/cpu-features.c1313
-rw-r--r--thirdparty/libvpx/third_party/android/cpu-features.h323
-rw-r--r--thirdparty/libwebp/src/dec/alphai_dec.h2
-rw-r--r--thirdparty/libwebp/src/dec/buffer_dec.c3
-rw-r--r--thirdparty/libwebp/src/dec/common_dec.h2
-rw-r--r--thirdparty/libwebp/src/dec/frame_dec.c9
-rw-r--r--thirdparty/libwebp/src/dec/idec_dec.c25
-rw-r--r--thirdparty/libwebp/src/dec/vp8_dec.h2
-rw-r--r--thirdparty/libwebp/src/dec/vp8i_dec.h4
-rw-r--r--thirdparty/libwebp/src/dec/vp8l_dec.c103
-rw-r--r--thirdparty/libwebp/src/dec/vp8li_dec.h2
-rw-r--r--thirdparty/libwebp/src/dec/webpi_dec.h2
-rw-r--r--thirdparty/libwebp/src/demux/demux.c2
-rw-r--r--thirdparty/libwebp/src/dsp/dsp.h6
-rw-r--r--thirdparty/libwebp/src/dsp/enc.c6
-rw-r--r--thirdparty/libwebp/src/dsp/enc_avx2.c21
-rw-r--r--thirdparty/libwebp/src/dsp/lossless.c2
-rw-r--r--thirdparty/libwebp/src/dsp/lossless.h14
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc.c86
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc_mips32.c79
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc_sse2.c44
-rw-r--r--thirdparty/libwebp/src/dsp/msa_macro.h2
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler.c4
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler_mips32.c4
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c10
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler_msa.c7
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler_neon.c18
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler_sse2.c35
-rw-r--r--thirdparty/libwebp/src/dsp/yuv.h2
-rw-r--r--thirdparty/libwebp/src/enc/analysis_enc.c2
-rw-r--r--thirdparty/libwebp/src/enc/backward_references_cost_enc.c2
-rw-r--r--thirdparty/libwebp/src/enc/backward_references_enc.c1
-rw-r--r--thirdparty/libwebp/src/enc/cost_enc.h2
-rw-r--r--thirdparty/libwebp/src/enc/delta_palettization_enc.c455
-rw-r--r--thirdparty/libwebp/src/enc/delta_palettization_enc.h25
-rw-r--r--thirdparty/libwebp/src/enc/histogram_enc.c196
-rw-r--r--thirdparty/libwebp/src/enc/histogram_enc.h10
-rw-r--r--thirdparty/libwebp/src/enc/iterator_enc.c2
-rw-r--r--thirdparty/libwebp/src/enc/picture_tools_enc.c41
-rw-r--r--thirdparty/libwebp/src/enc/vp8i_enc.h6
-rw-r--r--thirdparty/libwebp/src/enc/vp8l_enc.c17
-rw-r--r--thirdparty/libwebp/src/enc/vp8li_enc.h2
-rw-r--r--thirdparty/libwebp/src/mux/animi.h2
-rw-r--r--thirdparty/libwebp/src/mux/muxedit.c18
-rw-r--r--thirdparty/libwebp/src/mux/muxi.h18
-rw-r--r--thirdparty/libwebp/src/mux/muxinternal.c53
-rw-r--r--thirdparty/libwebp/src/mux/muxread.c61
-rw-r--r--thirdparty/libwebp/src/utils/bit_reader_inl_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/bit_reader_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/bit_writer_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/filters_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/quant_levels_dec_utils.c8
-rw-r--r--thirdparty/libwebp/src/utils/quant_levels_dec_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/quant_levels_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/random_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/rescaler_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/thread_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/utils.h2
-rw-r--r--thirdparty/libwebp/src/webp/decode.h2
-rw-r--r--thirdparty/libwebp/src/webp/demux.h2
-rw-r--r--thirdparty/libwebp/src/webp/encode.h2
-rw-r--r--thirdparty/libwebp/src/webp/format_constants.h2
-rw-r--r--thirdparty/libwebp/src/webp/mux.h2
-rw-r--r--thirdparty/libwebp/src/webp/mux_types.h2
-rw-r--r--thirdparty/libwebp/src/webp/types.h2
-rw-r--r--thirdparty/libwebsockets/core/context.c25
-rw-r--r--thirdparty/libwebsockets/core/libwebsockets.c55
-rw-r--r--thirdparty/libwebsockets/core/output.c12
-rw-r--r--thirdparty/libwebsockets/core/private.h33
-rw-r--r--thirdparty/libwebsockets/libwebsockets.h44
-rw-r--r--thirdparty/libwebsockets/lws_config.h2
-rw-r--r--thirdparty/libwebsockets/lws_config_private.h2
-rw-r--r--thirdparty/libwebsockets/misc/lejp.c25
-rw-r--r--thirdparty/libwebsockets/plat/lws-plat-unix.c10
-rw-r--r--thirdparty/libwebsockets/plat/lws-plat-win.c34
-rw-r--r--thirdparty/libwebsockets/roles/h1/ops-h1.c14
-rw-r--r--thirdparty/libwebsockets/roles/http/client/client-handshake.c10
-rw-r--r--thirdparty/libwebsockets/roles/http/client/client.c38
-rw-r--r--thirdparty/libwebsockets/roles/http/header.c76
-rw-r--r--thirdparty/libwebsockets/roles/http/private.h1
-rw-r--r--thirdparty/libwebsockets/roles/http/server/lejp-conf.c64
-rw-r--r--thirdparty/libwebsockets/roles/http/server/parsers.c26
-rw-r--r--thirdparty/libwebsockets/roles/http/server/server.c50
-rw-r--r--thirdparty/libwebsockets/roles/ws/client-parser-ws.c11
-rw-r--r--thirdparty/libwebsockets/roles/ws/ops-ws.c26
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/mbedtls-server.c2
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/ssl.c2
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_types.h4
-rw-r--r--thirdparty/libwebsockets/uwp_fixes.diff10
-rw-r--r--thirdparty/libwebsockets/win32helpers/getopt.c306
-rw-r--r--thirdparty/libwebsockets/win32helpers/getopt_long.c480
-rw-r--r--thirdparty/libwebsockets/win32helpers/gettimeofday.c70
-rw-r--r--thirdparty/misc/ifaddrs-android.cc221
-rw-r--r--thirdparty/misc/ifaddrs-android.h46
-rw-r--r--thirdparty/squish/Add-Decompress-Bc5-to-Squish.patch143
-rw-r--r--thirdparty/squish/colourblock.cpp89
-rw-r--r--thirdparty/squish/godot-changes.patch102
-rw-r--r--thirdparty/tinyexr/tinyexr.h253
104 files changed, 4470 insertions, 2829 deletions
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 7fdd9e20b0..5e42436f32 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -31,7 +31,7 @@ Files extracted from upstream source:
## certs
- Upstream: Mozilla, via https://apps.fedoraproject.org/packages/ca-certificates
-- Version: 2018.2.22
+- Version: 2018.2.26
- License: MPL 2.0
File extracted from a recent Fedora install:
@@ -128,7 +128,7 @@ Files extracted from upstream source:
## glad
- Upstream: https://github.com/Dav1dde/glad
-- Version: 0.1.25
+- Version: 0.1.28
- License: MIT
The files we package are automatically generated.
@@ -229,11 +229,14 @@ TODO.
Important: File `libvpx/vpx_dsp/x86/vpx_subpixel_8t_intrin_avx2.c` has
Godot-made change marked with `// -- GODOT --` comments.
+The files `libvpx/third_party/android/cpu-features.{c,h}` were copied
+from the Android NDK r18.
+
## libwebp
- Upstream: https://chromium.googlesource.com/webm/libwebp/
-- Version: 1.0.0
+- Version: 1.0.1
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -264,9 +267,7 @@ File extracted from upstream source:
- From `roles/ws` exclude `ext` folder.
- From `tls` exclude `openssl` folder.
- Also copy `win32helpers/` from `win32port/` inside `thirdparty/libwebsockets`
-- A small fix has been added in `libwebsockets/libwebsockets.h` to `#include <sys/socket.h>` for the BSD family.
- This change has been PRed upstream, and should be merged before the next update. Remember to check and remove this line.
-- Another fix has been added to allow building for 32-bits UWP, replacing `GetFileSize[Ex]` and `CreateFileW` with supported functions.
+- A fix has been added to allow building for 32-bits UWP, replacing `GetFileSize[Ex]` and `CreateFileW` with supported functions.
There is a diff for this change in `thirdparty/libwebsockets/uwp_fixes.diff`
Important: `lws_config.h` and `lws_config_private.h` contains custom
@@ -339,6 +340,10 @@ Collection of single-file libraries used in Godot components.
* Upstream: http://www.efgh.com/software/md5.htm
* Version: TBD, might not be latest from above URL
* License: RSA Message-Digest License
+- `open-simplex-noise.{c,h}`
+ * Upstream: https://github.com/smcameron/open-simplex-noise-in-c
+ * Version: git (0d555e7, 2015)
+ * License: Unlicense
- `pcg.{cpp,h}`
* Upstream: http://www.pcg-random.org
* Version: minimal C implementation, http://www.pcg-random.org/download.html
@@ -356,11 +361,6 @@ Collection of single-file libraries used in Godot components.
* Upstream: https://github.com/ivanfratric/polypartition (`src/polypartition.cpp`)
* Version: TBD, class was renamed
* License: MIT
-- `open-simplex-noise.{c,h}`
- * Upstream: https://github.com/smcameron/open-simplex-noise-in-c
- * Version: git (0d555e7, 2015)
- * License: Unlicense
-
### modules
@@ -373,6 +373,13 @@ Collection of single-file libraries used in Godot components.
* Version: ?
* License: BSD
+### platform
+
+- `ifaddrs-android.{cc,h}`
+ * Upstream: https://chromium.googlesource.com/external/webrtc/stable/talk/+/master/base/ifaddrs-android.h
+ * Version: 5976650 (2013)
+ * License: BSD-3-Clause
+
### scene
- `easing_equations.cpp`
@@ -505,7 +512,7 @@ changes are marked with `// -- GODOT --` comments.
## tinyexr
- Upstream: https://github.com/syoyo/tinyexr
-- Version: git (2d5375f, 2018)
+- Version: git (5ae30aa, 2018)
- License: BSD-3-Clause
Files extracted from upstream source:
diff --git a/thirdparty/certs/ca-certificates.crt b/thirdparty/certs/ca-certificates.crt
index 01dd29097e..613456b6d3 100644
--- a/thirdparty/certs/ca-certificates.crt
+++ b/thirdparty/certs/ca-certificates.crt
@@ -695,55 +695,6 @@ kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
l7+ijrRU
-----END CERTIFICATE-----
-# Certplus Root CA G1
------BEGIN CERTIFICATE-----
-MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA
-MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy
-dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa
-MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy
-dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
-ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a
-iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt
-6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP
-0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f
-6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE
-EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN
-1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc
-h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT
-mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV
-4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO
-WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud
-DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd
-Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq
-hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh
-66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7
-/SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS
-S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j
-2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R
-Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr
-RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy
-6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV
-V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5
-g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl
-++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo=
------END CERTIFICATE-----
-
-# Certplus Root CA G2
------BEGIN CERTIFICATE-----
-MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x
-CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs
-dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x
-CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs
-dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat
-93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x
-Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P
-AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj
-FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG
-SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch
-p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal
-U5ORGpOucGpnutee5WEaXw==
------END CERTIFICATE-----
-
# Certum Trusted Network CA
-----BEGIN CERTIFICATE-----
MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM
@@ -1679,6 +1630,40 @@ Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
WD9f
-----END CERTIFICATE-----
+# GlobalSign Root CA - R6
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg
+MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx
+MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET
+MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI
+xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k
+ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD
+aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw
+LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw
+1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX
+k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2
+SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h
+bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n
+WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY
+rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce
+MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu
+bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt
+Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61
+55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj
+vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf
+cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz
+oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp
+nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs
+pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v
+JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R
+8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4
+5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
+
# Global Chambersign Root - 2008
-----BEGIN CERTIFICATE-----
MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD
@@ -2175,88 +2160,21 @@ aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
-----END CERTIFICATE-----
-# OpenTrust Root CA G1
------BEGIN CERTIFICATE-----
-MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA
-MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w
-ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw
-MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU
-T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
-AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b
-wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX
-/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0
-77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP
-uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx
-p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx
-Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2
-TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W
-G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw
-vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY
-EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO
-BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1
-2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw
-DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E
-PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf
-gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS
-FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0
-V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P
-XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I
-i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t
-TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91
-09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky
-Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ
-AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj
-1oxx
------END CERTIFICATE-----
-
-# OpenTrust Root CA G2
------BEGIN CERTIFICATE-----
-MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA
-MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w
-ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw
-MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU
-T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
-AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh
-/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e
-CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6
-1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE
-FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS
-gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X
-G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy
-YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH
-vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4
-t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/
-gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO
-BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3
-5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w
-DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz
-Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0
-nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT
-RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT
-wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2
-t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa
-TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2
-o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU
-3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA
-iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f
-WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM
-S1IK
------END CERTIFICATE-----
-
-# OpenTrust Root CA G3
------BEGIN CERTIFICATE-----
-MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx
-CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U
-cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow
-QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl
-blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm
-3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d
-oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G
-A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5
-DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK
-BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q
-j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx
-4nxp5V2a+EEfOzmTk51V6s2N8fvB
+# OISTE WISeKey Global Root GC CA
+-----BEGIN CERTIFICATE-----
+MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw
+CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91
+bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg
+Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ
+BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu
+ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS
+b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni
+eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W
+p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T
+rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV
+57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg
+Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
-----END CERTIFICATE-----
# QuoVadis Root CA
@@ -3302,33 +3220,6 @@ jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN
ZetX2fNXlrtIzYE=
-----END CERTIFICATE-----
-# TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5
------BEGIN CERTIFICATE-----
-MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UE
-BhMCVFIxDzANBgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxn
-aSDEsGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkg
-QS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1QgRWxla3Ryb25payBTZXJ0aWZpa2Eg
-SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAwODA3MDFaFw0yMzA0
-MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYD
-VQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8
-dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF
-bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIB
-IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApCUZ4WWe60ghUEoI5RHwWrom
-/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537jVJp45wnEFPzpALFp/kR
-Gml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1mep5Fimh3
-4khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z
-5UNP9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0
-hO8EuPbJbKoCPrZV4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QID
-AQABo0IwQDAdBgNVHQ4EFgQUVpkHHtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/
-BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ5FdnsX
-SDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPoBP5yCccLqh0l
-VX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq
-URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nf
-peYVhDfwwvJllpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CF
-Yv4HAqGEVka+lgqaE9chTLd8B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW
-+qtB4Uu2NQvAmxU=
------END CERTIFICATE-----
-
# USERTrust ECC Certification Authority
-----BEGIN CERTIFICATE-----
MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
diff --git a/thirdparty/enet/godot.cpp b/thirdparty/enet/godot.cpp
index 6ba7cf0000..73a09f9b1d 100644
--- a/thirdparty/enet/godot.cpp
+++ b/thirdparty/enet/godot.cpp
@@ -33,7 +33,7 @@
*/
#include "core/io/ip.h"
-#include "core/io/packet_peer_udp.h"
+#include "core/io/net_socket.h"
#include "core/os/os.h"
// This must be last for windows to compile (tested with MinGW)
@@ -90,6 +90,16 @@ int enet_address_get_host(const ENetAddress *address, char *name, size_t nameLen
return -1;
}
+ENetSocket enet_socket_create(ENetSocketType type) {
+
+ NetSocket *socket = NetSocket::create();
+ IP::Type ip_type = IP::TYPE_ANY;
+ socket->open(NetSocket::TYPE_UDP, ip_type);
+ socket->set_blocking_enabled(false);
+
+ return socket;
+}
+
int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
IP_Address ip;
@@ -99,23 +109,15 @@ int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
ip.set_ipv6(address->host);
}
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
- if (sock->listen(address->port, ip) != OK) {
+ NetSocket *sock = (NetSocket *)socket;
+ if (sock->bind(ip, address->port) != OK) {
return -1;
}
return 0;
}
-ENetSocket enet_socket_create(ENetSocketType type) {
-
- PacketPeerUDP *socket = memnew(PacketPeerUDP);
- socket->set_blocking_mode(false);
-
- return socket;
-}
-
void enet_socket_destroy(ENetSocket socket) {
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
+ NetSocket *sock = (NetSocket *)socket;
sock->close();
memdelete(sock);
}
@@ -124,13 +126,12 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
ERR_FAIL_COND_V(address == NULL, -1);
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
+ NetSocket *sock = (NetSocket *)socket;
IP_Address dest;
Error err;
size_t i = 0;
dest.set_ipv6(address->host);
- sock->set_dest_address(dest, address->port);
// Create a single packet.
PoolVector<uint8_t> out;
@@ -148,7 +149,8 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
pos += buffers[i].dataLength;
}
- err = sock->put_packet((const uint8_t *)&w[0], size);
+ int sent = 0;
+ err = sock->sendto((const uint8_t *)&w[0], size, sent, dest, address->port);
if (err != OK) {
if (err == ERR_BUSY) { // Blocking call
@@ -159,32 +161,36 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
return -1;
}
- return size;
+ return sent;
}
int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
ERR_FAIL_COND_V(bufferCount != 1, -1);
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
+ NetSocket *sock = (NetSocket *)socket;
- int pc = sock->get_available_packet_count();
- if (pc < 1) {
- return pc;
- }
+ Error ret = sock->poll(NetSocket::POLL_TYPE_IN, 0);
- const uint8_t *buffer;
- int buffer_size;
- Error err = sock->get_packet(&buffer, buffer_size);
- if (err)
+ if (ret == ERR_BUSY)
+ return 0;
+
+ if (ret != OK)
return -1;
- copymem(buffers[0].data, buffer, buffer_size);
+ int read;
+ IP_Address ip;
- enet_address_set_ip(address, sock->get_packet_address().get_ipv6(), 16);
- address->port = sock->get_packet_port();
+ Error err = sock->recvfrom((uint8_t *)buffers[0].data, buffers[0].dataLength, read, ip, address->port);
+ if (err == ERR_BUSY)
+ return 0;
+
+ if (err != OK)
+ return -1;
+
+ enet_address_set_ip(address, ip.get_ipv6(), 16);
- return buffer_size;
+ return read;
}
// Not implemented
diff --git a/thirdparty/freetype/include/freetype/config/ftoption.h b/thirdparty/freetype/include/freetype/config/ftoption.h
index 4bcab2af5c..1fc7295a2c 100644
--- a/thirdparty/freetype/include/freetype/config/ftoption.h
+++ b/thirdparty/freetype/include/freetype/config/ftoption.h
@@ -178,7 +178,7 @@ FT_BEGIN_HEADER
/* */
/* Define this macro if you want to enable this `feature'. */
/* */
-#define FT_CONFIG_OPTION_USE_LZW
+/* #define FT_CONFIG_OPTION_USE_LZW */ // -GODOT-
/*************************************************************************/
@@ -193,7 +193,7 @@ FT_BEGIN_HEADER
/* Define this macro if you want to enable this `feature'. See also */
/* the macro FT_CONFIG_OPTION_SYSTEM_ZLIB below. */
/* */
-#define FT_CONFIG_OPTION_USE_ZLIB
+/* #define FT_CONFIG_OPTION_USE_ZLIB */ // -GODOT-
/*************************************************************************/
diff --git a/thirdparty/glad/glad.c b/thirdparty/glad/glad.c
index 35469e9031..8cc09e46e1 100644
--- a/thirdparty/glad/glad.c
+++ b/thirdparty/glad/glad.c
@@ -1,6 +1,6 @@
/*
- OpenGL loader generated by glad 0.1.25 on Sat Jul 28 10:59:43 2018.
+ OpenGL loader generated by glad 0.1.28 on Thu Nov 22 16:50:04 2018.
Language/Generator: C/C++
Specification: gl
@@ -13,11 +13,12 @@
Loader: True
Local files: False
Omit khrplatform: False
+ Reproducible: False
Commandline:
--profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_object"
Online:
- http://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_object
+ https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_object
*/
#include <stdio.h>
@@ -154,7 +155,7 @@ int gladLoadGL(void) {
return status;
}
-struct gladGLversionStruct GLVersion;
+struct gladGLversionStruct GLVersion = { 0, 0 };
#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
#define _GLAD_IS_SOME_NEW_VERSION 1
@@ -179,7 +180,11 @@ static int get_exts(void) {
num_exts_i = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i);
if (num_exts_i > 0) {
- exts_i = (char **)realloc((void *)exts_i, (size_t)num_exts_i * (sizeof *exts_i));
+ char **tmp_exts_i = (char **)realloc((void *)exts_i, (size_t)num_exts_i * (sizeof *exts_i));
+ if (tmp_exts_i == NULL) {
+ return 0;
+ }
+ exts_i = tmp_exts_i;
}
if (exts_i == NULL) {
@@ -253,766 +258,766 @@ static int has_ext(const char *ext) {
return 0;
}
-int GLAD_GL_VERSION_1_0;
-int GLAD_GL_VERSION_1_1;
-int GLAD_GL_VERSION_1_2;
-int GLAD_GL_VERSION_1_3;
-int GLAD_GL_VERSION_1_4;
-int GLAD_GL_VERSION_1_5;
-int GLAD_GL_VERSION_2_0;
-int GLAD_GL_VERSION_2_1;
-int GLAD_GL_VERSION_3_0;
-int GLAD_GL_VERSION_3_1;
-int GLAD_GL_VERSION_3_2;
-int GLAD_GL_VERSION_3_3;
-PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
-PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
-PFNGLWINDOWPOS2SPROC glad_glWindowPos2s;
-PFNGLWINDOWPOS2IPROC glad_glWindowPos2i;
-PFNGLWINDOWPOS2FPROC glad_glWindowPos2f;
-PFNGLWINDOWPOS2DPROC glad_glWindowPos2d;
-PFNGLVERTEX2FVPROC glad_glVertex2fv;
-PFNGLINDEXIPROC glad_glIndexi;
-PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
-PFNGLRECTDVPROC glad_glRectdv;
-PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
-PFNGLEVALCOORD2DPROC glad_glEvalCoord2d;
-PFNGLEVALCOORD2FPROC glad_glEvalCoord2f;
-PFNGLINDEXDPROC glad_glIndexd;
-PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
-PFNGLINDEXFPROC glad_glIndexf;
-PFNGLBINDSAMPLERPROC glad_glBindSampler;
-PFNGLLINEWIDTHPROC glad_glLineWidth;
-PFNGLCOLORP3UIVPROC glad_glColorP3uiv;
-PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
-PFNGLGETMAPFVPROC glad_glGetMapfv;
-PFNGLINDEXSPROC glad_glIndexs;
-PFNGLCOMPILESHADERPROC glad_glCompileShader;
-PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
-PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv;
-PFNGLINDEXFVPROC glad_glIndexfv;
-PFNGLFOGIVPROC glad_glFogiv;
-PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
-PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv;
-PFNGLLIGHTMODELIVPROC glad_glLightModeliv;
-PFNGLCOLOR4UIPROC glad_glColor4ui;
-PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv;
-PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui;
-PFNGLFOGFVPROC glad_glFogfv;
-PFNGLVERTEXP4UIPROC glad_glVertexP4ui;
-PFNGLENABLEIPROC glad_glEnablei;
-PFNGLVERTEX4IVPROC glad_glVertex4iv;
-PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv;
-PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv;
-PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
-PFNGLCREATESHADERPROC glad_glCreateShader;
-PFNGLISBUFFERPROC glad_glIsBuffer;
-PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
-PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
-PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
-PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
-PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
-PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
-PFNGLVERTEX4FVPROC glad_glVertex4fv;
-PFNGLBINDTEXTUREPROC glad_glBindTexture;
-PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
-PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv;
-PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
-PFNGLVERTEXP2UIPROC glad_glVertexP2ui;
-PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
-PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv;
-PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
-PFNGLPOINTSIZEPROC glad_glPointSize;
-PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
-PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
-PFNGLCOLOR4BVPROC glad_glColor4bv;
-PFNGLRASTERPOS2FPROC glad_glRasterPos2f;
-PFNGLRASTERPOS2DPROC glad_glRasterPos2d;
-PFNGLLOADIDENTITYPROC glad_glLoadIdentity;
-PFNGLRASTERPOS2IPROC glad_glRasterPos2i;
-PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
-PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
-PFNGLCOLOR3BPROC glad_glColor3b;
-PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
-PFNGLEDGEFLAGPROC glad_glEdgeFlag;
-PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
-PFNGLVERTEX3DPROC glad_glVertex3d;
-PFNGLVERTEX3FPROC glad_glVertex3f;
-PFNGLVERTEX3IPROC glad_glVertex3i;
-PFNGLCOLOR3IPROC glad_glColor3i;
-PFNGLUNIFORM3FPROC glad_glUniform3f;
-PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
-PFNGLCOLOR3SPROC glad_glColor3s;
-PFNGLVERTEX3SPROC glad_glVertex3s;
-PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui;
-PFNGLCOLORMASKIPROC glad_glColorMaski;
-PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
-PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv;
-PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
-PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui;
-PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
-PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
-PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
-PFNGLVERTEX2IVPROC glad_glVertex2iv;
-PFNGLCOLOR3SVPROC glad_glColor3sv;
-PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
-PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
-PFNGLNORMALPOINTERPROC glad_glNormalPointer;
-PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv;
-PFNGLVERTEX4SVPROC glad_glVertex4sv;
-PFNGLPASSTHROUGHPROC glad_glPassThrough;
-PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui;
-PFNGLFOGIPROC glad_glFogi;
-PFNGLBEGINPROC glad_glBegin;
-PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv;
-PFNGLCOLOR3UBVPROC glad_glColor3ubv;
-PFNGLVERTEXPOINTERPROC glad_glVertexPointer;
-PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv;
-PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
-PFNGLDRAWARRAYSPROC glad_glDrawArrays;
-PFNGLUNIFORM1UIPROC glad_glUniform1ui;
-PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d;
-PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f;
-PFNGLLIGHTFVPROC glad_glLightfv;
-PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui;
-PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
-PFNGLCLEARPROC glad_glClear;
-PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i;
-PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
-PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s;
-PFNGLISENABLEDPROC glad_glIsEnabled;
-PFNGLSTENCILOPPROC glad_glStencilOp;
-PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
-PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
-PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
-PFNGLTRANSLATEFPROC glad_glTranslatef;
-PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
-PFNGLTRANSLATEDPROC glad_glTranslated;
-PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv;
-PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
-PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
-PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv;
-PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
-PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv;
-PFNGLGETMATERIALFVPROC glad_glGetMaterialfv;
-PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
-PFNGLFOGCOORDFVPROC glad_glFogCoordfv;
-PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv;
-PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
-PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
-PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
-PFNGLINDEXSVPROC glad_glIndexsv;
-PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
-PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
-PFNGLVERTEX3IVPROC glad_glVertex3iv;
-PFNGLBITMAPPROC glad_glBitmap;
-PFNGLMATERIALIPROC glad_glMateriali;
-PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
-PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
-PFNGLGETQUERYIVPROC glad_glGetQueryiv;
-PFNGLTEXCOORD4FPROC glad_glTexCoord4f;
-PFNGLTEXCOORD4DPROC glad_glTexCoord4d;
-PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
-PFNGLTEXCOORD4IPROC glad_glTexCoord4i;
-PFNGLMATERIALFPROC glad_glMaterialf;
-PFNGLTEXCOORD4SPROC glad_glTexCoord4s;
-PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
-PFNGLISSHADERPROC glad_glIsShader;
-PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s;
-PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
-PFNGLVERTEX3DVPROC glad_glVertex3dv;
-PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
-PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
-PFNGLENABLEPROC glad_glEnable;
-PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
-PFNGLCOLOR4FVPROC glad_glColor4fv;
-PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv;
-PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv;
-PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
-PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv;
-PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i;
-PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv;
-PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv;
-PFNGLTEXGENFPROC glad_glTexGenf;
-PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv;
-PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
-PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui;
-PFNGLGETPOINTERVPROC glad_glGetPointerv;
-PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
-PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
-PFNGLNORMAL3FVPROC glad_glNormal3fv;
-PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s;
-PFNGLDEPTHRANGEPROC glad_glDepthRange;
-PFNGLFRUSTUMPROC glad_glFrustum;
-PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv;
-PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
-PFNGLPUSHMATRIXPROC glad_glPushMatrix;
-PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv;
-PFNGLORTHOPROC glad_glOrtho;
-PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
-PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv;
-PFNGLCLEARINDEXPROC glad_glClearIndex;
-PFNGLMAP1DPROC glad_glMap1d;
-PFNGLMAP1FPROC glad_glMap1f;
-PFNGLFLUSHPROC glad_glFlush;
-PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
-PFNGLINDEXIVPROC glad_glIndexiv;
-PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv;
-PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
-PFNGLPIXELZOOMPROC glad_glPixelZoom;
-PFNGLFENCESYNCPROC glad_glFenceSync;
-PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
-PFNGLCOLORP3UIPROC glad_glColorP3ui;
-PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
-PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
-PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
-PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
-PFNGLLIGHTIPROC glad_glLighti;
-PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv;
-PFNGLLIGHTFPROC glad_glLightf;
-PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
-PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
-PFNGLGENSAMPLERSPROC glad_glGenSamplers;
-PFNGLCLAMPCOLORPROC glad_glClampColor;
-PFNGLUNIFORM4IVPROC glad_glUniform4iv;
-PFNGLCLEARSTENCILPROC glad_glClearStencil;
-PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv;
-PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv;
-PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv;
-PFNGLGENTEXTURESPROC glad_glGenTextures;
-PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv;
-PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
-PFNGLINDEXPOINTERPROC glad_glIndexPointer;
-PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
-PFNGLISSYNCPROC glad_glIsSync;
-PFNGLVERTEX2FPROC glad_glVertex2f;
-PFNGLVERTEX2DPROC glad_glVertex2d;
-PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
-PFNGLUNIFORM2IPROC glad_glUniform2i;
-PFNGLMAPGRID2DPROC glad_glMapGrid2d;
-PFNGLMAPGRID2FPROC glad_glMapGrid2f;
-PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui;
-PFNGLVERTEX2IPROC glad_glVertex2i;
-PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
-PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
-PFNGLVERTEX2SPROC glad_glVertex2s;
-PFNGLNORMAL3BVPROC glad_glNormal3bv;
-PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
-PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
-PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv;
-PFNGLVERTEX3SVPROC glad_glVertex3sv;
-PFNGLGENQUERIESPROC glad_glGenQueries;
-PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv;
-PFNGLTEXENVFPROC glad_glTexEnvf;
-PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
-PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
-PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
-PFNGLFOGCOORDDPROC glad_glFogCoordd;
-PFNGLFOGCOORDFPROC glad_glFogCoordf;
-PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
-PFNGLTEXENVIPROC glad_glTexEnvi;
-PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv;
-PFNGLISENABLEDIPROC glad_glIsEnabledi;
-PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui;
-PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
-PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
-PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv;
-PFNGLUNIFORM2IVPROC glad_glUniform2iv;
-PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
-PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
-PFNGLMATRIXMODEPROC glad_glMatrixMode;
-PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer;
-PFNGLGETMAPIVPROC glad_glGetMapiv;
-PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
-PFNGLGETSHADERIVPROC glad_glGetShaderiv;
-PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d;
-PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f;
-PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
-PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures;
-PFNGLCALLLISTPROC glad_glCallList;
-PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv;
-PFNGLGETDOUBLEVPROC glad_glGetDoublev;
-PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv;
-PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
-PFNGLLIGHTMODELFPROC glad_glLightModelf;
-PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
-PFNGLVERTEX2SVPROC glad_glVertex2sv;
-PFNGLLIGHTMODELIPROC glad_glLightModeli;
-PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv;
-PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv;
-PFNGLUNIFORM3FVPROC glad_glUniform3fv;
-PFNGLPIXELSTOREIPROC glad_glPixelStorei;
-PFNGLCALLLISTSPROC glad_glCallLists;
-PFNGLMAPBUFFERPROC glad_glMapBuffer;
-PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d;
-PFNGLTEXCOORD3IPROC glad_glTexCoord3i;
-PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv;
-PFNGLRASTERPOS3IPROC glad_glRasterPos3i;
-PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b;
-PFNGLRASTERPOS3DPROC glad_glRasterPos3d;
-PFNGLRASTERPOS3FPROC glad_glRasterPos3f;
-PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
-PFNGLTEXCOORD3FPROC glad_glTexCoord3f;
-PFNGLDELETESYNCPROC glad_glDeleteSync;
-PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
-PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
-PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
-PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
-PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
-PFNGLTEXCOORD3SPROC glad_glTexCoord3s;
-PFNGLUNIFORM3IVPROC glad_glUniform3iv;
-PFNGLRASTERPOS3SPROC glad_glRasterPos3s;
-PFNGLPOLYGONMODEPROC glad_glPolygonMode;
-PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
-PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
-PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident;
-PFNGLISLISTPROC glad_glIsList;
-PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv;
-PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv;
-PFNGLCOLOR4SPROC glad_glColor4s;
-PFNGLUSEPROGRAMPROC glad_glUseProgram;
-PFNGLLINESTIPPLEPROC glad_glLineStipple;
-PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv;
-PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
-PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
-PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv;
-PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
-PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
-PFNGLCOLOR4BPROC glad_glColor4b;
-PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f;
-PFNGLCOLOR4FPROC glad_glColor4f;
-PFNGLCOLOR4DPROC glad_glColor4d;
-PFNGLCOLOR4IPROC glad_glColor4i;
-PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
-PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
-PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv;
-PFNGLVERTEX2DVPROC glad_glVertex2dv;
-PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv;
-PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
-PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
-PFNGLFINISHPROC glad_glFinish;
-PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
-PFNGLDELETESHADERPROC glad_glDeleteShader;
-PFNGLDRAWELEMENTSPROC glad_glDrawElements;
-PFNGLRASTERPOS2SPROC glad_glRasterPos2s;
-PFNGLGETMAPDVPROC glad_glGetMapdv;
-PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
-PFNGLMATERIALFVPROC glad_glMaterialfv;
-PFNGLVIEWPORTPROC glad_glViewport;
-PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
-PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
-PFNGLINDEXDVPROC glad_glIndexdv;
-PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
-PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv;
-PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
-PFNGLCLEARDEPTHPROC glad_glClearDepth;
-PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
-PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
-PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
-PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
-PFNGLTEXBUFFERPROC glad_glTexBuffer;
-PFNGLPOPNAMEPROC glad_glPopName;
-PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
-PFNGLPIXELSTOREFPROC glad_glPixelStoref;
-PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
-PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv;
-PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv;
-PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv;
-PFNGLRECTIPROC glad_glRecti;
-PFNGLCOLOR4UBPROC glad_glColor4ub;
-PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf;
-PFNGLRECTFPROC glad_glRectf;
-PFNGLRECTDPROC glad_glRectd;
-PFNGLNORMAL3SVPROC glad_glNormal3sv;
-PFNGLNEWLISTPROC glad_glNewList;
-PFNGLCOLOR4USPROC glad_glColor4us;
-PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
-PFNGLLINKPROGRAMPROC glad_glLinkProgram;
-PFNGLHINTPROC glad_glHint;
-PFNGLRECTSPROC glad_glRects;
-PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv;
-PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv;
-PFNGLGETSTRINGPROC glad_glGetString;
-PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
-PFNGLEDGEFLAGVPROC glad_glEdgeFlagv;
-PFNGLDETACHSHADERPROC glad_glDetachShader;
-PFNGLSCALEFPROC glad_glScalef;
-PFNGLENDQUERYPROC glad_glEndQuery;
-PFNGLSCALEDPROC glad_glScaled;
-PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer;
-PFNGLCOPYPIXELSPROC glad_glCopyPixels;
-PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
-PFNGLPOPATTRIBPROC glad_glPopAttrib;
-PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
-PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
-PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
-PFNGLNORMALP3UIVPROC glad_glNormalP3uiv;
-PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
-PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
-PFNGLINITNAMESPROC glad_glInitNames;
-PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
-PFNGLCOLOR3DVPROC glad_glColor3dv;
-PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
-PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
-PFNGLWAITSYNCPROC glad_glWaitSync;
-PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
-PFNGLCOLORMATERIALPROC glad_glColorMaterial;
-PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
-PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
-PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
-PFNGLUNIFORM1FPROC glad_glUniform1f;
-PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
-PFNGLRENDERMODEPROC glad_glRenderMode;
-PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
-PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv;
-PFNGLUNIFORM1IPROC glad_glUniform1i;
-PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
-PFNGLUNIFORM3IPROC glad_glUniform3i;
-PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi;
-PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
-PFNGLDISABLEPROC glad_glDisable;
-PFNGLLOGICOPPROC glad_glLogicOp;
-PFNGLEVALPOINT2PROC glad_glEvalPoint2;
-PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf;
-PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i;
-PFNGLUNIFORM4UIPROC glad_glUniform4ui;
-PFNGLCOLOR3FPROC glad_glColor3f;
-PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
-PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv;
-PFNGLRECTFVPROC glad_glRectfv;
-PFNGLCULLFACEPROC glad_glCullFace;
-PFNGLGETLIGHTFVPROC glad_glGetLightfv;
-PFNGLCOLOR3DPROC glad_glColor3d;
-PFNGLTEXGENDPROC glad_glTexGend;
-PFNGLTEXGENIPROC glad_glTexGeni;
-PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s;
-PFNGLGETSTRINGIPROC glad_glGetStringi;
-PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i;
-PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f;
-PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d;
-PFNGLATTACHSHADERPROC glad_glAttachShader;
-PFNGLFOGCOORDDVPROC glad_glFogCoorddv;
-PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
-PFNGLGETTEXGENFVPROC glad_glGetTexGenfv;
-PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
-PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer;
-PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
-PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
-PFNGLTEXGENIVPROC glad_glTexGeniv;
-PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv;
-PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv;
-PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture;
-PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
-PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us;
-PFNGLNORMALP3UIPROC glad_glNormalP3ui;
-PFNGLTEXENVFVPROC glad_glTexEnvfv;
-PFNGLREADBUFFERPROC glad_glReadBuffer;
-PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
-PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
-PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
-PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv;
-PFNGLLIGHTMODELFVPROC glad_glLightModelfv;
-PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
-PFNGLDELETELISTSPROC glad_glDeleteLists;
-PFNGLGETCLIPPLANEPROC glad_glGetClipPlane;
-PFNGLVERTEX4DVPROC glad_glVertex4dv;
-PFNGLTEXCOORD2DPROC glad_glTexCoord2d;
-PFNGLPOPMATRIXPROC glad_glPopMatrix;
-PFNGLTEXCOORD2FPROC glad_glTexCoord2f;
-PFNGLCOLOR4IVPROC glad_glColor4iv;
-PFNGLINDEXUBVPROC glad_glIndexubv;
-PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
-PFNGLTEXCOORD2IPROC glad_glTexCoord2i;
-PFNGLRASTERPOS4DPROC glad_glRasterPos4d;
-PFNGLRASTERPOS4FPROC glad_glRasterPos4f;
-PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
-PFNGLTEXCOORD2SPROC glad_glTexCoord2s;
-PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
-PFNGLVERTEX3FVPROC glad_glVertex3fv;
-PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv;
-PFNGLMATERIALIVPROC glad_glMaterialiv;
-PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
-PFNGLISPROGRAMPROC glad_glIsProgram;
-PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
-PFNGLVERTEX4SPROC glad_glVertex4s;
-PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
-PFNGLNORMAL3DVPROC glad_glNormal3dv;
-PFNGLUNIFORM4IPROC glad_glUniform4i;
-PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
-PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
-PFNGLROTATEDPROC glad_glRotated;
-PFNGLROTATEFPROC glad_glRotatef;
-PFNGLVERTEX4IPROC glad_glVertex4i;
-PFNGLREADPIXELSPROC glad_glReadPixels;
-PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
-PFNGLLOADNAMEPROC glad_glLoadName;
-PFNGLUNIFORM4FPROC glad_glUniform4f;
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
-PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
-PFNGLSHADEMODELPROC glad_glShadeModel;
-PFNGLMAPGRID1DPROC glad_glMapGrid1d;
-PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
-PFNGLMAPGRID1FPROC glad_glMapGrid1f;
-PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
-PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState;
-PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv;
-PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
-PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer;
-PFNGLALPHAFUNCPROC glad_glAlphaFunc;
-PFNGLUNIFORM1IVPROC glad_glUniform1iv;
-PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv;
-PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
-PFNGLSTENCILFUNCPROC glad_glStencilFunc;
-PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv;
-PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
-PFNGLCOLOR4UIVPROC glad_glColor4uiv;
-PFNGLRECTIVPROC glad_glRectiv;
-PFNGLCOLORP4UIPROC glad_glColorP4ui;
-PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv;
-PFNGLEVALMESH2PROC glad_glEvalMesh2;
-PFNGLEVALMESH1PROC glad_glEvalMesh1;
-PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer;
-PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
-PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
-PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv;
-PFNGLCOLOR4UBVPROC glad_glColor4ubv;
-PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd;
-PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf;
-PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
-PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv;
-PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
-PFNGLTEXENVIVPROC glad_glTexEnviv;
-PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
-PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
-PFNGLGENBUFFERSPROC glad_glGenBuffers;
-PFNGLSELECTBUFFERPROC glad_glSelectBuffer;
-PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
-PFNGLPUSHATTRIBPROC glad_glPushAttrib;
-PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
-PFNGLBLENDFUNCPROC glad_glBlendFunc;
-PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
-PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
-PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
-PFNGLLIGHTIVPROC glad_glLightiv;
-PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
-PFNGLTEXGENFVPROC glad_glTexGenfv;
-PFNGLENDPROC glad_glEnd;
-PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
-PFNGLSCISSORPROC glad_glScissor;
-PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv;
-PFNGLCLIPPLANEPROC glad_glClipPlane;
-PFNGLPUSHNAMEPROC glad_glPushName;
-PFNGLTEXGENDVPROC glad_glTexGendv;
-PFNGLINDEXUBPROC glad_glIndexub;
-PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv;
-PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv;
-PFNGLRASTERPOS4IPROC glad_glRasterPos4i;
-PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd;
-PFNGLCLEARCOLORPROC glad_glClearColor;
-PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
-PFNGLNORMAL3SPROC glad_glNormal3s;
-PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
-PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
-PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
-PFNGLCOLORP4UIVPROC glad_glColorP4uiv;
-PFNGLBLENDCOLORPROC glad_glBlendColor;
-PFNGLWINDOWPOS3DPROC glad_glWindowPos3d;
-PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
-PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
-PFNGLUNIFORM3UIPROC glad_glUniform3ui;
-PFNGLCOLOR4DVPROC glad_glColor4dv;
-PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
-PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
-PFNGLUNIFORM2FVPROC glad_glUniform2fv;
-PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub;
-PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui;
-PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv;
-PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
-PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
-PFNGLNORMAL3IVPROC glad_glNormal3iv;
-PFNGLWINDOWPOS3SPROC glad_glWindowPos3s;
-PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
-PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
-PFNGLWINDOWPOS3IPROC glad_glWindowPos3i;
-PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s;
-PFNGLWINDOWPOS3FPROC glad_glWindowPos3f;
-PFNGLCOLOR3USPROC glad_glColor3us;
-PFNGLCOLOR3UIVPROC glad_glColor3uiv;
-PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
-PFNGLGETLIGHTIVPROC glad_glGetLightiv;
-PFNGLDEPTHFUNCPROC glad_glDepthFunc;
-PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
-PFNGLLISTBASEPROC glad_glListBase;
-PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f;
-PFNGLCOLOR3UBPROC glad_glColor3ub;
-PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d;
-PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
-PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
-PFNGLCOLOR3UIPROC glad_glColor3ui;
-PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i;
-PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple;
-PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
-PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
-PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv;
-PFNGLCOLORMASKPROC glad_glColorMask;
-PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
-PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
-PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
-PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
-PFNGLRASTERPOS4SPROC glad_glRasterPos4s;
-PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
-PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
-PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv;
-PFNGLCOLOR4SVPROC glad_glColor4sv;
-PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib;
-PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
-PFNGLFOGFPROC glad_glFogf;
-PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
-PFNGLISSAMPLERPROC glad_glIsSampler;
-PFNGLVERTEXP3UIPROC glad_glVertexP3ui;
-PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
-PFNGLCOLOR3IVPROC glad_glColor3iv;
-PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
-PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
-PFNGLTEXCOORD1IPROC glad_glTexCoord1i;
-PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
-PFNGLTEXCOORD1DPROC glad_glTexCoord1d;
-PFNGLTEXCOORD1FPROC glad_glTexCoord1f;
-PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
-PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState;
-PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
-PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
-PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv;
-PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
-PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
-PFNGLTEXCOORD1SPROC glad_glTexCoord1s;
-PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
-PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
-PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
-PFNGLGENLISTSPROC glad_glGenLists;
-PFNGLCOLOR3BVPROC glad_glColor3bv;
-PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
-PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
-PFNGLGETTEXGENDVPROC glad_glGetTexGendv;
-PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
-PFNGLENDLISTPROC glad_glEndList;
-PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv;
-PFNGLUNIFORM2UIPROC glad_glUniform2ui;
-PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
-PFNGLCOLOR3USVPROC glad_glColor3usv;
-PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv;
-PFNGLDISABLEIPROC glad_glDisablei;
-PFNGLINDEXMASKPROC glad_glIndexMask;
-PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib;
-PFNGLSHADERSOURCEPROC glad_glShaderSource;
-PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
-PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
-PFNGLCLEARACCUMPROC glad_glClearAccum;
-PFNGLGETSYNCIVPROC glad_glGetSynciv;
-PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv;
-PFNGLUNIFORM2FPROC glad_glUniform2f;
-PFNGLBEGINQUERYPROC glad_glBeginQuery;
-PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
-PFNGLBINDBUFFERPROC glad_glBindBuffer;
-PFNGLMAP2DPROC glad_glMap2d;
-PFNGLMAP2FPROC glad_glMap2f;
-PFNGLVERTEX4DPROC glad_glVertex4d;
-PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
-PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv;
-PFNGLBUFFERDATAPROC glad_glBufferData;
-PFNGLEVALPOINT1PROC glad_glEvalPoint1;
-PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
-PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv;
-PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui;
-PFNGLGETERRORPROC glad_glGetError;
-PFNGLGETTEXENVIVPROC glad_glGetTexEnviv;
-PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
-PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
-PFNGLGETFLOATVPROC glad_glGetFloatv;
-PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
-PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv;
-PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
-PFNGLEVALCOORD1DPROC glad_glEvalCoord1d;
-PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
-PFNGLEVALCOORD1FPROC glad_glEvalCoord1f;
-PFNGLPIXELMAPFVPROC glad_glPixelMapfv;
-PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
-PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv;
-PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
-PFNGLGETINTEGERVPROC glad_glGetIntegerv;
-PFNGLACCUMPROC glad_glAccum;
-PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
-PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
-PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv;
-PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv;
-PFNGLISQUERYPROC glad_glIsQuery;
-PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
-PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv;
-PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
-PFNGLSTENCILMASKPROC glad_glStencilMask;
-PFNGLDRAWPIXELSPROC glad_glDrawPixels;
-PFNGLMULTMATRIXDPROC glad_glMultMatrixd;
-PFNGLMULTMATRIXFPROC glad_glMultMatrixf;
-PFNGLISTEXTUREPROC glad_glIsTexture;
-PFNGLGETMATERIALIVPROC glad_glGetMaterialiv;
-PFNGLUNIFORM1FVPROC glad_glUniform1fv;
-PFNGLLOADMATRIXFPROC glad_glLoadMatrixf;
-PFNGLLOADMATRIXDPROC glad_glLoadMatrixd;
-PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
-PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
-PFNGLVERTEX4FPROC glad_glVertex4f;
-PFNGLRECTSVPROC glad_glRectsv;
-PFNGLCOLOR4USVPROC glad_glColor4usv;
-PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple;
-PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays;
-PFNGLNORMAL3IPROC glad_glNormal3i;
-PFNGLNORMAL3FPROC glad_glNormal3f;
-PFNGLNORMAL3DPROC glad_glNormal3d;
-PFNGLNORMAL3BPROC glad_glNormal3b;
-PFNGLPIXELMAPUSVPROC glad_glPixelMapusv;
-PFNGLGETTEXGENIVPROC glad_glGetTexGeniv;
-PFNGLARRAYELEMENTPROC glad_glArrayElement;
-PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
-PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
-PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
-PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
-PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
-PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
-PFNGLDEPTHMASKPROC glad_glDepthMask;
-PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
-PFNGLCOLOR3FVPROC glad_glColor3fv;
-PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
-PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
-PFNGLUNIFORM4FVPROC glad_glUniform4fv;
-PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
-PFNGLCOLORPOINTERPROC glad_glColorPointer;
-PFNGLFRONTFACEPROC glad_glFrontFace;
-PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
-PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
-int GLAD_GL_ARB_framebuffer_object;
-int GLAD_GL_EXT_framebuffer_object;
-int GLAD_GL_ARB_debug_output;
-PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB;
-PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB;
-PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB;
-PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB;
-PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT;
-PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT;
-PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT;
-PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT;
-PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT;
-PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT;
-PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT;
-PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT;
-PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT;
-PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT;
-PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT;
-PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT;
-PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT;
-PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT;
-PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT;
-PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT;
-PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT;
+int GLAD_GL_VERSION_1_0 = 0;
+int GLAD_GL_VERSION_1_1 = 0;
+int GLAD_GL_VERSION_1_2 = 0;
+int GLAD_GL_VERSION_1_3 = 0;
+int GLAD_GL_VERSION_1_4 = 0;
+int GLAD_GL_VERSION_1_5 = 0;
+int GLAD_GL_VERSION_2_0 = 0;
+int GLAD_GL_VERSION_2_1 = 0;
+int GLAD_GL_VERSION_3_0 = 0;
+int GLAD_GL_VERSION_3_1 = 0;
+int GLAD_GL_VERSION_3_2 = 0;
+int GLAD_GL_VERSION_3_3 = 0;
+PFNGLACCUMPROC glad_glAccum = NULL;
+PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
+PFNGLALPHAFUNCPROC glad_glAlphaFunc = NULL;
+PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident = NULL;
+PFNGLARRAYELEMENTPROC glad_glArrayElement = NULL;
+PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
+PFNGLBEGINPROC glad_glBegin = NULL;
+PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL;
+PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
+PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
+PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
+PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
+PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
+PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL;
+PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL;
+PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
+PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
+PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
+PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
+PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
+PFNGLBITMAPPROC glad_glBitmap = NULL;
+PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
+PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
+PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
+PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
+PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
+PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
+PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
+PFNGLCALLLISTPROC glad_glCallList = NULL;
+PFNGLCALLLISTSPROC glad_glCallLists = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
+PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
+PFNGLCLEARPROC glad_glClear = NULL;
+PFNGLCLEARACCUMPROC glad_glClearAccum = NULL;
+PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
+PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
+PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
+PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
+PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
+PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
+PFNGLCLEARINDEXPROC glad_glClearIndex = NULL;
+PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
+PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture = NULL;
+PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
+PFNGLCLIPPLANEPROC glad_glClipPlane = NULL;
+PFNGLCOLOR3BPROC glad_glColor3b = NULL;
+PFNGLCOLOR3BVPROC glad_glColor3bv = NULL;
+PFNGLCOLOR3DPROC glad_glColor3d = NULL;
+PFNGLCOLOR3DVPROC glad_glColor3dv = NULL;
+PFNGLCOLOR3FPROC glad_glColor3f = NULL;
+PFNGLCOLOR3FVPROC glad_glColor3fv = NULL;
+PFNGLCOLOR3IPROC glad_glColor3i = NULL;
+PFNGLCOLOR3IVPROC glad_glColor3iv = NULL;
+PFNGLCOLOR3SPROC glad_glColor3s = NULL;
+PFNGLCOLOR3SVPROC glad_glColor3sv = NULL;
+PFNGLCOLOR3UBPROC glad_glColor3ub = NULL;
+PFNGLCOLOR3UBVPROC glad_glColor3ubv = NULL;
+PFNGLCOLOR3UIPROC glad_glColor3ui = NULL;
+PFNGLCOLOR3UIVPROC glad_glColor3uiv = NULL;
+PFNGLCOLOR3USPROC glad_glColor3us = NULL;
+PFNGLCOLOR3USVPROC glad_glColor3usv = NULL;
+PFNGLCOLOR4BPROC glad_glColor4b = NULL;
+PFNGLCOLOR4BVPROC glad_glColor4bv = NULL;
+PFNGLCOLOR4DPROC glad_glColor4d = NULL;
+PFNGLCOLOR4DVPROC glad_glColor4dv = NULL;
+PFNGLCOLOR4FPROC glad_glColor4f = NULL;
+PFNGLCOLOR4FVPROC glad_glColor4fv = NULL;
+PFNGLCOLOR4IPROC glad_glColor4i = NULL;
+PFNGLCOLOR4IVPROC glad_glColor4iv = NULL;
+PFNGLCOLOR4SPROC glad_glColor4s = NULL;
+PFNGLCOLOR4SVPROC glad_glColor4sv = NULL;
+PFNGLCOLOR4UBPROC glad_glColor4ub = NULL;
+PFNGLCOLOR4UBVPROC glad_glColor4ubv = NULL;
+PFNGLCOLOR4UIPROC glad_glColor4ui = NULL;
+PFNGLCOLOR4UIVPROC glad_glColor4uiv = NULL;
+PFNGLCOLOR4USPROC glad_glColor4us = NULL;
+PFNGLCOLOR4USVPROC glad_glColor4usv = NULL;
+PFNGLCOLORMASKPROC glad_glColorMask = NULL;
+PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
+PFNGLCOLORMATERIALPROC glad_glColorMaterial = NULL;
+PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL;
+PFNGLCOLORP3UIVPROC glad_glColorP3uiv = NULL;
+PFNGLCOLORP4UIPROC glad_glColorP4ui = NULL;
+PFNGLCOLORP4UIVPROC glad_glColorP4uiv = NULL;
+PFNGLCOLORPOINTERPROC glad_glColorPointer = NULL;
+PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
+PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
+PFNGLCOPYPIXELSPROC glad_glCopyPixels = NULL;
+PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
+PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
+PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
+PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
+PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
+PFNGLCULLFACEPROC glad_glCullFace = NULL;
+PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
+PFNGLDELETELISTSPROC glad_glDeleteLists = NULL;
+PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
+PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
+PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
+PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
+PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
+PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
+PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
+PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
+PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
+PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
+PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL;
+PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
+PFNGLDISABLEPROC glad_glDisable = NULL;
+PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
+PFNGLDISABLEIPROC glad_glDisablei = NULL;
+PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
+PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
+PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
+PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
+PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL;
+PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
+PFNGLDRAWPIXELSPROC glad_glDrawPixels = NULL;
+PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
+PFNGLEDGEFLAGPROC glad_glEdgeFlag = NULL;
+PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer = NULL;
+PFNGLEDGEFLAGVPROC glad_glEdgeFlagv = NULL;
+PFNGLENABLEPROC glad_glEnable = NULL;
+PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
+PFNGLENABLEIPROC glad_glEnablei = NULL;
+PFNGLENDPROC glad_glEnd = NULL;
+PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
+PFNGLENDLISTPROC glad_glEndList = NULL;
+PFNGLENDQUERYPROC glad_glEndQuery = NULL;
+PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
+PFNGLEVALCOORD1DPROC glad_glEvalCoord1d = NULL;
+PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv = NULL;
+PFNGLEVALCOORD1FPROC glad_glEvalCoord1f = NULL;
+PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv = NULL;
+PFNGLEVALCOORD2DPROC glad_glEvalCoord2d = NULL;
+PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv = NULL;
+PFNGLEVALCOORD2FPROC glad_glEvalCoord2f = NULL;
+PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv = NULL;
+PFNGLEVALMESH1PROC glad_glEvalMesh1 = NULL;
+PFNGLEVALMESH2PROC glad_glEvalMesh2 = NULL;
+PFNGLEVALPOINT1PROC glad_glEvalPoint1 = NULL;
+PFNGLEVALPOINT2PROC glad_glEvalPoint2 = NULL;
+PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer = NULL;
+PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
+PFNGLFINISHPROC glad_glFinish = NULL;
+PFNGLFLUSHPROC glad_glFlush = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
+PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer = NULL;
+PFNGLFOGCOORDDPROC glad_glFogCoordd = NULL;
+PFNGLFOGCOORDDVPROC glad_glFogCoorddv = NULL;
+PFNGLFOGCOORDFPROC glad_glFogCoordf = NULL;
+PFNGLFOGCOORDFVPROC glad_glFogCoordfv = NULL;
+PFNGLFOGFPROC glad_glFogf = NULL;
+PFNGLFOGFVPROC glad_glFogfv = NULL;
+PFNGLFOGIPROC glad_glFogi = NULL;
+PFNGLFOGIVPROC glad_glFogiv = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
+PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
+PFNGLFRUSTUMPROC glad_glFrustum = NULL;
+PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
+PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
+PFNGLGENLISTSPROC glad_glGenLists = NULL;
+PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
+PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
+PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
+PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
+PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
+PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
+PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
+PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
+PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL;
+PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
+PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
+PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL;
+PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
+PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
+PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
+PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
+PFNGLGETCLIPPLANEPROC glad_glGetClipPlane = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
+PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
+PFNGLGETERRORPROC glad_glGetError = NULL;
+PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
+PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL;
+PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
+PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
+PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
+PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
+PFNGLGETLIGHTFVPROC glad_glGetLightfv = NULL;
+PFNGLGETLIGHTIVPROC glad_glGetLightiv = NULL;
+PFNGLGETMAPDVPROC glad_glGetMapdv = NULL;
+PFNGLGETMAPFVPROC glad_glGetMapfv = NULL;
+PFNGLGETMAPIVPROC glad_glGetMapiv = NULL;
+PFNGLGETMATERIALFVPROC glad_glGetMaterialfv = NULL;
+PFNGLGETMATERIALIVPROC glad_glGetMaterialiv = NULL;
+PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
+PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv = NULL;
+PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv = NULL;
+PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv = NULL;
+PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
+PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple = NULL;
+PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
+PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
+PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
+PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL;
+PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
+PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
+PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL;
+PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
+PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
+PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
+PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
+PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
+PFNGLGETSTRINGPROC glad_glGetString = NULL;
+PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
+PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
+PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv = NULL;
+PFNGLGETTEXENVIVPROC glad_glGetTexEnviv = NULL;
+PFNGLGETTEXGENDVPROC glad_glGetTexGendv = NULL;
+PFNGLGETTEXGENFVPROC glad_glGetTexGenfv = NULL;
+PFNGLGETTEXGENIVPROC glad_glGetTexGeniv = NULL;
+PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL;
+PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL;
+PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL;
+PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
+PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
+PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
+PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
+PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
+PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
+PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
+PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
+PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
+PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
+PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
+PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
+PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
+PFNGLHINTPROC glad_glHint = NULL;
+PFNGLINDEXMASKPROC glad_glIndexMask = NULL;
+PFNGLINDEXPOINTERPROC glad_glIndexPointer = NULL;
+PFNGLINDEXDPROC glad_glIndexd = NULL;
+PFNGLINDEXDVPROC glad_glIndexdv = NULL;
+PFNGLINDEXFPROC glad_glIndexf = NULL;
+PFNGLINDEXFVPROC glad_glIndexfv = NULL;
+PFNGLINDEXIPROC glad_glIndexi = NULL;
+PFNGLINDEXIVPROC glad_glIndexiv = NULL;
+PFNGLINDEXSPROC glad_glIndexs = NULL;
+PFNGLINDEXSVPROC glad_glIndexsv = NULL;
+PFNGLINDEXUBPROC glad_glIndexub = NULL;
+PFNGLINDEXUBVPROC glad_glIndexubv = NULL;
+PFNGLINITNAMESPROC glad_glInitNames = NULL;
+PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays = NULL;
+PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
+PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
+PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL;
+PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
+PFNGLISLISTPROC glad_glIsList = NULL;
+PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
+PFNGLISQUERYPROC glad_glIsQuery = NULL;
+PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
+PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
+PFNGLISSHADERPROC glad_glIsShader = NULL;
+PFNGLISSYNCPROC glad_glIsSync = NULL;
+PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
+PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
+PFNGLLIGHTMODELFPROC glad_glLightModelf = NULL;
+PFNGLLIGHTMODELFVPROC glad_glLightModelfv = NULL;
+PFNGLLIGHTMODELIPROC glad_glLightModeli = NULL;
+PFNGLLIGHTMODELIVPROC glad_glLightModeliv = NULL;
+PFNGLLIGHTFPROC glad_glLightf = NULL;
+PFNGLLIGHTFVPROC glad_glLightfv = NULL;
+PFNGLLIGHTIPROC glad_glLighti = NULL;
+PFNGLLIGHTIVPROC glad_glLightiv = NULL;
+PFNGLLINESTIPPLEPROC glad_glLineStipple = NULL;
+PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
+PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
+PFNGLLISTBASEPROC glad_glListBase = NULL;
+PFNGLLOADIDENTITYPROC glad_glLoadIdentity = NULL;
+PFNGLLOADMATRIXDPROC glad_glLoadMatrixd = NULL;
+PFNGLLOADMATRIXFPROC glad_glLoadMatrixf = NULL;
+PFNGLLOADNAMEPROC glad_glLoadName = NULL;
+PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd = NULL;
+PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf = NULL;
+PFNGLLOGICOPPROC glad_glLogicOp = NULL;
+PFNGLMAP1DPROC glad_glMap1d = NULL;
+PFNGLMAP1FPROC glad_glMap1f = NULL;
+PFNGLMAP2DPROC glad_glMap2d = NULL;
+PFNGLMAP2FPROC glad_glMap2f = NULL;
+PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
+PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
+PFNGLMAPGRID1DPROC glad_glMapGrid1d = NULL;
+PFNGLMAPGRID1FPROC glad_glMapGrid1f = NULL;
+PFNGLMAPGRID2DPROC glad_glMapGrid2d = NULL;
+PFNGLMAPGRID2FPROC glad_glMapGrid2f = NULL;
+PFNGLMATERIALFPROC glad_glMaterialf = NULL;
+PFNGLMATERIALFVPROC glad_glMaterialfv = NULL;
+PFNGLMATERIALIPROC glad_glMateriali = NULL;
+PFNGLMATERIALIVPROC glad_glMaterialiv = NULL;
+PFNGLMATRIXMODEPROC glad_glMatrixMode = NULL;
+PFNGLMULTMATRIXDPROC glad_glMultMatrixd = NULL;
+PFNGLMULTMATRIXFPROC glad_glMultMatrixf = NULL;
+PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd = NULL;
+PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf = NULL;
+PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
+PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
+PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d = NULL;
+PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv = NULL;
+PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f = NULL;
+PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv = NULL;
+PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i = NULL;
+PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv = NULL;
+PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s = NULL;
+PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv = NULL;
+PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d = NULL;
+PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv = NULL;
+PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f = NULL;
+PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv = NULL;
+PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i = NULL;
+PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv = NULL;
+PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s = NULL;
+PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv = NULL;
+PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d = NULL;
+PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv = NULL;
+PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f = NULL;
+PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv = NULL;
+PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i = NULL;
+PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv = NULL;
+PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s = NULL;
+PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv = NULL;
+PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d = NULL;
+PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv = NULL;
+PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f = NULL;
+PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv = NULL;
+PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i = NULL;
+PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv = NULL;
+PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s = NULL;
+PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv = NULL;
+PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL;
+PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL;
+PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL;
+PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv = NULL;
+PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL;
+PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL;
+PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL;
+PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL;
+PFNGLNEWLISTPROC glad_glNewList = NULL;
+PFNGLNORMAL3BPROC glad_glNormal3b = NULL;
+PFNGLNORMAL3BVPROC glad_glNormal3bv = NULL;
+PFNGLNORMAL3DPROC glad_glNormal3d = NULL;
+PFNGLNORMAL3DVPROC glad_glNormal3dv = NULL;
+PFNGLNORMAL3FPROC glad_glNormal3f = NULL;
+PFNGLNORMAL3FVPROC glad_glNormal3fv = NULL;
+PFNGLNORMAL3IPROC glad_glNormal3i = NULL;
+PFNGLNORMAL3IVPROC glad_glNormal3iv = NULL;
+PFNGLNORMAL3SPROC glad_glNormal3s = NULL;
+PFNGLNORMAL3SVPROC glad_glNormal3sv = NULL;
+PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL;
+PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL;
+PFNGLNORMALPOINTERPROC glad_glNormalPointer = NULL;
+PFNGLORTHOPROC glad_glOrtho = NULL;
+PFNGLPASSTHROUGHPROC glad_glPassThrough = NULL;
+PFNGLPIXELMAPFVPROC glad_glPixelMapfv = NULL;
+PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv = NULL;
+PFNGLPIXELMAPUSVPROC glad_glPixelMapusv = NULL;
+PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL;
+PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
+PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf = NULL;
+PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi = NULL;
+PFNGLPIXELZOOMPROC glad_glPixelZoom = NULL;
+PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL;
+PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL;
+PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL;
+PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
+PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
+PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
+PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
+PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple = NULL;
+PFNGLPOPATTRIBPROC glad_glPopAttrib = NULL;
+PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib = NULL;
+PFNGLPOPMATRIXPROC glad_glPopMatrix = NULL;
+PFNGLPOPNAMEPROC glad_glPopName = NULL;
+PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
+PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures = NULL;
+PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL;
+PFNGLPUSHATTRIBPROC glad_glPushAttrib = NULL;
+PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib = NULL;
+PFNGLPUSHMATRIXPROC glad_glPushMatrix = NULL;
+PFNGLPUSHNAMEPROC glad_glPushName = NULL;
+PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL;
+PFNGLRASTERPOS2DPROC glad_glRasterPos2d = NULL;
+PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv = NULL;
+PFNGLRASTERPOS2FPROC glad_glRasterPos2f = NULL;
+PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv = NULL;
+PFNGLRASTERPOS2IPROC glad_glRasterPos2i = NULL;
+PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv = NULL;
+PFNGLRASTERPOS2SPROC glad_glRasterPos2s = NULL;
+PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv = NULL;
+PFNGLRASTERPOS3DPROC glad_glRasterPos3d = NULL;
+PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv = NULL;
+PFNGLRASTERPOS3FPROC glad_glRasterPos3f = NULL;
+PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv = NULL;
+PFNGLRASTERPOS3IPROC glad_glRasterPos3i = NULL;
+PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv = NULL;
+PFNGLRASTERPOS3SPROC glad_glRasterPos3s = NULL;
+PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv = NULL;
+PFNGLRASTERPOS4DPROC glad_glRasterPos4d = NULL;
+PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv = NULL;
+PFNGLRASTERPOS4FPROC glad_glRasterPos4f = NULL;
+PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv = NULL;
+PFNGLRASTERPOS4IPROC glad_glRasterPos4i = NULL;
+PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv = NULL;
+PFNGLRASTERPOS4SPROC glad_glRasterPos4s = NULL;
+PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv = NULL;
+PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
+PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
+PFNGLRECTDPROC glad_glRectd = NULL;
+PFNGLRECTDVPROC glad_glRectdv = NULL;
+PFNGLRECTFPROC glad_glRectf = NULL;
+PFNGLRECTFVPROC glad_glRectfv = NULL;
+PFNGLRECTIPROC glad_glRecti = NULL;
+PFNGLRECTIVPROC glad_glRectiv = NULL;
+PFNGLRECTSPROC glad_glRects = NULL;
+PFNGLRECTSVPROC glad_glRectsv = NULL;
+PFNGLRENDERMODEPROC glad_glRenderMode = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
+PFNGLROTATEDPROC glad_glRotated = NULL;
+PFNGLROTATEFPROC glad_glRotatef = NULL;
+PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
+PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL;
+PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL;
+PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL;
+PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
+PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
+PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
+PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
+PFNGLSCALEDPROC glad_glScaled = NULL;
+PFNGLSCALEFPROC glad_glScalef = NULL;
+PFNGLSCISSORPROC glad_glScissor = NULL;
+PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b = NULL;
+PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv = NULL;
+PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d = NULL;
+PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv = NULL;
+PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f = NULL;
+PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv = NULL;
+PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i = NULL;
+PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv = NULL;
+PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s = NULL;
+PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv = NULL;
+PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub = NULL;
+PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv = NULL;
+PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui = NULL;
+PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv = NULL;
+PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us = NULL;
+PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv = NULL;
+PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui = NULL;
+PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL;
+PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer = NULL;
+PFNGLSELECTBUFFERPROC glad_glSelectBuffer = NULL;
+PFNGLSHADEMODELPROC glad_glShadeModel = NULL;
+PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
+PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
+PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
+PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
+PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
+PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL;
+PFNGLTEXCOORD1DPROC glad_glTexCoord1d = NULL;
+PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv = NULL;
+PFNGLTEXCOORD1FPROC glad_glTexCoord1f = NULL;
+PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv = NULL;
+PFNGLTEXCOORD1IPROC glad_glTexCoord1i = NULL;
+PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv = NULL;
+PFNGLTEXCOORD1SPROC glad_glTexCoord1s = NULL;
+PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv = NULL;
+PFNGLTEXCOORD2DPROC glad_glTexCoord2d = NULL;
+PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv = NULL;
+PFNGLTEXCOORD2FPROC glad_glTexCoord2f = NULL;
+PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv = NULL;
+PFNGLTEXCOORD2IPROC glad_glTexCoord2i = NULL;
+PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv = NULL;
+PFNGLTEXCOORD2SPROC glad_glTexCoord2s = NULL;
+PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv = NULL;
+PFNGLTEXCOORD3DPROC glad_glTexCoord3d = NULL;
+PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv = NULL;
+PFNGLTEXCOORD3FPROC glad_glTexCoord3f = NULL;
+PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv = NULL;
+PFNGLTEXCOORD3IPROC glad_glTexCoord3i = NULL;
+PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv = NULL;
+PFNGLTEXCOORD3SPROC glad_glTexCoord3s = NULL;
+PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv = NULL;
+PFNGLTEXCOORD4DPROC glad_glTexCoord4d = NULL;
+PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv = NULL;
+PFNGLTEXCOORD4FPROC glad_glTexCoord4f = NULL;
+PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv = NULL;
+PFNGLTEXCOORD4IPROC glad_glTexCoord4i = NULL;
+PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv = NULL;
+PFNGLTEXCOORD4SPROC glad_glTexCoord4s = NULL;
+PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv = NULL;
+PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui = NULL;
+PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv = NULL;
+PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui = NULL;
+PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv = NULL;
+PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui = NULL;
+PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv = NULL;
+PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui = NULL;
+PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv = NULL;
+PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer = NULL;
+PFNGLTEXENVFPROC glad_glTexEnvf = NULL;
+PFNGLTEXENVFVPROC glad_glTexEnvfv = NULL;
+PFNGLTEXENVIPROC glad_glTexEnvi = NULL;
+PFNGLTEXENVIVPROC glad_glTexEnviv = NULL;
+PFNGLTEXGENDPROC glad_glTexGend = NULL;
+PFNGLTEXGENDVPROC glad_glTexGendv = NULL;
+PFNGLTEXGENFPROC glad_glTexGenf = NULL;
+PFNGLTEXGENFVPROC glad_glTexGenfv = NULL;
+PFNGLTEXGENIPROC glad_glTexGeni = NULL;
+PFNGLTEXGENIVPROC glad_glTexGeniv = NULL;
+PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL;
+PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL;
+PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL;
+PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL;
+PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL;
+PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
+PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
+PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
+PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
+PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
+PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
+PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
+PFNGLTRANSLATEDPROC glad_glTranslated = NULL;
+PFNGLTRANSLATEFPROC glad_glTranslatef = NULL;
+PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
+PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
+PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
+PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
+PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
+PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
+PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
+PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
+PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
+PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
+PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
+PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
+PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
+PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
+PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
+PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
+PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
+PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
+PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
+PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
+PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
+PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
+PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
+PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
+PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
+PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
+PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
+PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
+PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
+PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
+PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
+PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
+PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
+PFNGLVERTEX2DPROC glad_glVertex2d = NULL;
+PFNGLVERTEX2DVPROC glad_glVertex2dv = NULL;
+PFNGLVERTEX2FPROC glad_glVertex2f = NULL;
+PFNGLVERTEX2FVPROC glad_glVertex2fv = NULL;
+PFNGLVERTEX2IPROC glad_glVertex2i = NULL;
+PFNGLVERTEX2IVPROC glad_glVertex2iv = NULL;
+PFNGLVERTEX2SPROC glad_glVertex2s = NULL;
+PFNGLVERTEX2SVPROC glad_glVertex2sv = NULL;
+PFNGLVERTEX3DPROC glad_glVertex3d = NULL;
+PFNGLVERTEX3DVPROC glad_glVertex3dv = NULL;
+PFNGLVERTEX3FPROC glad_glVertex3f = NULL;
+PFNGLVERTEX3FVPROC glad_glVertex3fv = NULL;
+PFNGLVERTEX3IPROC glad_glVertex3i = NULL;
+PFNGLVERTEX3IVPROC glad_glVertex3iv = NULL;
+PFNGLVERTEX3SPROC glad_glVertex3s = NULL;
+PFNGLVERTEX3SVPROC glad_glVertex3sv = NULL;
+PFNGLVERTEX4DPROC glad_glVertex4d = NULL;
+PFNGLVERTEX4DVPROC glad_glVertex4dv = NULL;
+PFNGLVERTEX4FPROC glad_glVertex4f = NULL;
+PFNGLVERTEX4FVPROC glad_glVertex4fv = NULL;
+PFNGLVERTEX4IPROC glad_glVertex4i = NULL;
+PFNGLVERTEX4IVPROC glad_glVertex4iv = NULL;
+PFNGLVERTEX4SPROC glad_glVertex4s = NULL;
+PFNGLVERTEX4SVPROC glad_glVertex4sv = NULL;
+PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
+PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
+PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL;
+PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL;
+PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL;
+PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL;
+PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL;
+PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL;
+PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL;
+PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL;
+PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL;
+PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL;
+PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL;
+PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL;
+PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL;
+PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL;
+PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL;
+PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL;
+PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL;
+PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL;
+PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL;
+PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL;
+PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL;
+PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL;
+PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL;
+PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL;
+PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL;
+PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL;
+PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
+PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL;
+PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL;
+PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL;
+PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL;
+PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL;
+PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL;
+PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL;
+PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL;
+PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL;
+PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL;
+PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL;
+PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL;
+PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL;
+PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
+PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
+PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL;
+PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL;
+PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
+PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
+PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL;
+PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
+PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL;
+PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL;
+PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL;
+PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL;
+PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL;
+PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL;
+PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL;
+PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
+PFNGLVERTEXP2UIPROC glad_glVertexP2ui = NULL;
+PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv = NULL;
+PFNGLVERTEXP3UIPROC glad_glVertexP3ui = NULL;
+PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv = NULL;
+PFNGLVERTEXP4UIPROC glad_glVertexP4ui = NULL;
+PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv = NULL;
+PFNGLVERTEXPOINTERPROC glad_glVertexPointer = NULL;
+PFNGLVIEWPORTPROC glad_glViewport = NULL;
+PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
+PFNGLWINDOWPOS2DPROC glad_glWindowPos2d = NULL;
+PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv = NULL;
+PFNGLWINDOWPOS2FPROC glad_glWindowPos2f = NULL;
+PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv = NULL;
+PFNGLWINDOWPOS2IPROC glad_glWindowPos2i = NULL;
+PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv = NULL;
+PFNGLWINDOWPOS2SPROC glad_glWindowPos2s = NULL;
+PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv = NULL;
+PFNGLWINDOWPOS3DPROC glad_glWindowPos3d = NULL;
+PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv = NULL;
+PFNGLWINDOWPOS3FPROC glad_glWindowPos3f = NULL;
+PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv = NULL;
+PFNGLWINDOWPOS3IPROC glad_glWindowPos3i = NULL;
+PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv = NULL;
+PFNGLWINDOWPOS3SPROC glad_glWindowPos3s = NULL;
+PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv = NULL;
+int GLAD_GL_ARB_debug_output = 0;
+int GLAD_GL_ARB_framebuffer_object = 0;
+int GLAD_GL_EXT_framebuffer_object = 0;
+PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL;
+PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL;
+PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL;
+PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL;
+PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT = NULL;
+PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT = NULL;
+PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT = NULL;
+PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT = NULL;
+PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT = NULL;
+PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT = NULL;
+PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT = NULL;
+PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT = NULL;
+PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT = NULL;
static void load_GL_VERSION_1_0(GLADloadproc load) {
if(!GLAD_GL_VERSION_1_0) return;
glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace");
diff --git a/thirdparty/glad/glad/glad.h b/thirdparty/glad/glad/glad.h
index 4d92d33b37..52b05e0ae6 100644
--- a/thirdparty/glad/glad/glad.h
+++ b/thirdparty/glad/glad/glad.h
@@ -1,6 +1,6 @@
/*
- OpenGL loader generated by glad 0.1.25 on Sat Jul 28 10:59:43 2018.
+ OpenGL loader generated by glad 0.1.28 on Thu Nov 22 16:50:04 2018.
Language/Generator: C/C++
Specification: gl
@@ -13,11 +13,12 @@
Loader: True
Local files: False
Omit khrplatform: False
+ Reproducible: False
Commandline:
--profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_object"
Online:
- http://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_object
+ https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_object
*/
@@ -46,6 +47,10 @@
#define APIENTRYP APIENTRY *
#endif
+#ifndef GLAPIENTRY
+#define GLAPIENTRY APIENTRY
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -89,59 +94,21 @@ GLAPI int gladLoadGL(void);
GLAPI int gladLoadGLLoader(GLADloadproc);
-#include <stddef.h>
#include <KHR/khrplatform.h>
-#ifndef GLEXT_64_TYPES_DEFINED
-/* This code block is duplicated in glxext.h, so must be protected */
-#define GLEXT_64_TYPES_DEFINED
-/* Define int32_t, int64_t, and uint64_t types for UST/MSC */
-/* (as used in the GL_EXT_timer_query extension). */
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-#include <inttypes.h>
-#elif defined(__sun__) || defined(__digital__)
-#include <inttypes.h>
-#if defined(__STDC__)
-#if defined(__arch64__) || defined(_LP64)
-typedef long int int64_t;
-typedef unsigned long int uint64_t;
-#else
-typedef long long int int64_t;
-typedef unsigned long long int uint64_t;
-#endif /* __arch64__ */
-#endif /* __STDC__ */
-#elif defined( __VMS ) || defined(__sgi)
-#include <inttypes.h>
-#elif defined(__SCO__) || defined(__USLC__)
-#include <stdint.h>
-#elif defined(__UNIXOS2__) || defined(__SOL64__)
-typedef long int int32_t;
-typedef long long int int64_t;
-typedef unsigned long long int uint64_t;
-#elif defined(_WIN32) && defined(__GNUC__)
-#include <stdint.h>
-#elif defined(_WIN32)
-typedef __int32 int32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-#else
-/* Fallback if nothing above works */
-#include <inttypes.h>
-#endif
-#endif
typedef unsigned int GLenum;
typedef unsigned char GLboolean;
typedef unsigned int GLbitfield;
typedef void GLvoid;
-typedef signed char GLbyte;
-typedef short GLshort;
+typedef khronos_int8_t GLbyte;
+typedef khronos_uint8_t GLubyte;
+typedef khronos_int16_t GLshort;
+typedef khronos_uint16_t GLushort;
typedef int GLint;
-typedef int GLclampx;
-typedef unsigned char GLubyte;
-typedef unsigned short GLushort;
typedef unsigned int GLuint;
+typedef khronos_int32_t GLclampx;
typedef int GLsizei;
-typedef float GLfloat;
-typedef float GLclampf;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
typedef double GLdouble;
typedef double GLclampd;
typedef void *GLeglClientBufferEXT;
@@ -153,25 +120,17 @@ typedef void *GLhandleARB;
#else
typedef unsigned int GLhandleARB;
#endif
-typedef unsigned short GLhalfARB;
-typedef unsigned short GLhalf;
-typedef GLint GLfixed;
+typedef khronos_uint16_t GLhalf;
+typedef khronos_uint16_t GLhalfARB;
+typedef khronos_int32_t GLfixed;
typedef khronos_intptr_t GLintptr;
+typedef khronos_intptr_t GLintptrARB;
typedef khronos_ssize_t GLsizeiptr;
-typedef int64_t GLint64;
-typedef uint64_t GLuint64;
-#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
-typedef long GLintptrARB;
-#else
-typedef ptrdiff_t GLintptrARB;
-#endif
-#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
-typedef long GLsizeiptrARB;
-#else
-typedef ptrdiff_t GLsizeiptrARB;
-#endif
-typedef int64_t GLint64EXT;
-typedef uint64_t GLuint64EXT;
+typedef khronos_ssize_t GLsizeiptrARB;
+typedef khronos_int64_t GLint64;
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_uint64_t GLuint64EXT;
typedef struct __GLsync *GLsync;
struct _cl_context;
struct _cl_event;
diff --git a/thirdparty/libvpx/third_party/android/cpu-features.c b/thirdparty/libvpx/third_party/android/cpu-features.c
new file mode 100644
index 0000000000..e2bd749b01
--- /dev/null
+++ b/thirdparty/libvpx/third_party/android/cpu-features.c
@@ -0,0 +1,1313 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+
+/* ChangeLog for this library:
+ *
+ * NDK r10e?: Add MIPS MSA feature.
+ *
+ * NDK r10: Support for 64-bit CPUs (Intel, ARM & MIPS).
+ *
+ * NDK r8d: Add android_setCpu().
+ *
+ * NDK r8c: Add new ARM CPU features: VFPv2, VFP_D32, VFP_FP16,
+ * VFP_FMA, NEON_FMA, IDIV_ARM, IDIV_THUMB2 and iWMMXt.
+ *
+ * Rewrite the code to parse /proc/self/auxv instead of
+ * the "Features" field in /proc/cpuinfo.
+ *
+ * Dynamically allocate the buffer that hold the content
+ * of /proc/cpuinfo to deal with newer hardware.
+ *
+ * NDK r7c: Fix CPU count computation. The old method only reported the
+ * number of _active_ CPUs when the library was initialized,
+ * which could be less than the real total.
+ *
+ * NDK r5: Handle buggy kernels which report a CPU Architecture number of 7
+ * for an ARMv6 CPU (see below).
+ *
+ * Handle kernels that only report 'neon', and not 'vfpv3'
+ * (VFPv3 is mandated by the ARM architecture is Neon is implemented)
+ *
+ * Handle kernels that only report 'vfpv3d16', and not 'vfpv3'
+ *
+ * Fix x86 compilation. Report ANDROID_CPU_FAMILY_X86 in
+ * android_getCpuFamily().
+ *
+ * NDK r4: Initial release
+ */
+
+#include "cpu-features.h"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/system_properties.h>
+#include <unistd.h>
+
+static pthread_once_t g_once;
+static int g_inited;
+static AndroidCpuFamily g_cpuFamily;
+static uint64_t g_cpuFeatures;
+static int g_cpuCount;
+
+#ifdef __arm__
+static uint32_t g_cpuIdArm;
+#endif
+
+static const int android_cpufeatures_debug = 0;
+
+#define D(...) \
+ do { \
+ if (android_cpufeatures_debug) { \
+ printf(__VA_ARGS__); fflush(stdout); \
+ } \
+ } while (0)
+
+#ifdef __i386__
+static __inline__ void x86_cpuid(int func, int values[4])
+{
+ int a, b, c, d;
+ /* We need to preserve ebx since we're compiling PIC code */
+ /* this means we can't use "=b" for the second output register */
+ __asm__ __volatile__ ( \
+ "push %%ebx\n"
+ "cpuid\n" \
+ "mov %%ebx, %1\n"
+ "pop %%ebx\n"
+ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+ : "a" (func) \
+ );
+ values[0] = a;
+ values[1] = b;
+ values[2] = c;
+ values[3] = d;
+}
+#elif defined(__x86_64__)
+static __inline__ void x86_cpuid(int func, int values[4])
+{
+ int64_t a, b, c, d;
+ /* We need to preserve ebx since we're compiling PIC code */
+ /* this means we can't use "=b" for the second output register */
+ __asm__ __volatile__ ( \
+ "push %%rbx\n"
+ "cpuid\n" \
+ "mov %%rbx, %1\n"
+ "pop %%rbx\n"
+ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+ : "a" (func) \
+ );
+ values[0] = a;
+ values[1] = b;
+ values[2] = c;
+ values[3] = d;
+}
+#endif
+
+/* Get the size of a file by reading it until the end. This is needed
+ * because files under /proc do not always return a valid size when
+ * using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed.
+ */
+static int
+get_file_size(const char* pathname)
+{
+
+ int fd, result = 0;
+ char buffer[256];
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0) {
+ D("Can't open %s: %s\n", pathname, strerror(errno));
+ return -1;
+ }
+
+ for (;;) {
+ int ret = read(fd, buffer, sizeof buffer);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ D("Error while reading %s: %s\n", pathname, strerror(errno));
+ break;
+ }
+ if (ret == 0)
+ break;
+
+ result += ret;
+ }
+ close(fd);
+ return result;
+}
+
+/* Read the content of /proc/cpuinfo into a user-provided buffer.
+ * Return the length of the data, or -1 on error. Does *not*
+ * zero-terminate the content. Will not read more
+ * than 'buffsize' bytes.
+ */
+static int
+read_file(const char* pathname, char* buffer, size_t buffsize)
+{
+ int fd, count;
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0) {
+ D("Could not open %s: %s\n", pathname, strerror(errno));
+ return -1;
+ }
+ count = 0;
+ while (count < (int)buffsize) {
+ int ret = read(fd, buffer + count, buffsize - count);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ D("Error while reading from %s: %s\n", pathname, strerror(errno));
+ if (count == 0)
+ count = -1;
+ break;
+ }
+ if (ret == 0)
+ break;
+ count += ret;
+ }
+ close(fd);
+ return count;
+}
+
+#ifdef __arm__
+/* Extract the content of a the first occurence of a given field in
+ * the content of /proc/cpuinfo and return it as a heap-allocated
+ * string that must be freed by the caller.
+ *
+ * Return NULL if not found
+ */
+static char*
+extract_cpuinfo_field(const char* buffer, int buflen, const char* field)
+{
+ int fieldlen = strlen(field);
+ const char* bufend = buffer + buflen;
+ char* result = NULL;
+ int len;
+ const char *p, *q;
+
+ /* Look for first field occurence, and ensures it starts the line. */
+ p = buffer;
+ for (;;) {
+ p = memmem(p, bufend-p, field, fieldlen);
+ if (p == NULL)
+ goto EXIT;
+
+ if (p == buffer || p[-1] == '\n')
+ break;
+
+ p += fieldlen;
+ }
+
+ /* Skip to the first column followed by a space */
+ p += fieldlen;
+ p = memchr(p, ':', bufend-p);
+ if (p == NULL || p[1] != ' ')
+ goto EXIT;
+
+ /* Find the end of the line */
+ p += 2;
+ q = memchr(p, '\n', bufend-p);
+ if (q == NULL)
+ q = bufend;
+
+ /* Copy the line into a heap-allocated buffer */
+ len = q-p;
+ result = malloc(len+1);
+ if (result == NULL)
+ goto EXIT;
+
+ memcpy(result, p, len);
+ result[len] = '\0';
+
+EXIT:
+ return result;
+}
+
+/* Checks that a space-separated list of items contains one given 'item'.
+ * Returns 1 if found, 0 otherwise.
+ */
+static int
+has_list_item(const char* list, const char* item)
+{
+ const char* p = list;
+ int itemlen = strlen(item);
+
+ if (list == NULL)
+ return 0;
+
+ while (*p) {
+ const char* q;
+
+ /* skip spaces */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ /* find end of current list item */
+ q = p;
+ while (*q && *q != ' ' && *q != '\t')
+ q++;
+
+ if (itemlen == q-p && !memcmp(p, item, itemlen))
+ return 1;
+
+ /* skip to next item */
+ p = q;
+ }
+ return 0;
+}
+#endif /* __arm__ */
+
+/* Parse a number starting from 'input', but not going further
+ * than 'limit'. Return the value into '*result'.
+ *
+ * NOTE: Does not skip over leading spaces, or deal with sign characters.
+ * NOTE: Ignores overflows.
+ *
+ * The function returns NULL in case of error (bad format), or the new
+ * position after the decimal number in case of success (which will always
+ * be <= 'limit').
+ */
+static const char*
+parse_number(const char* input, const char* limit, int base, int* result)
+{
+ const char* p = input;
+ int val = 0;
+ while (p < limit) {
+ int d = (*p - '0');
+ if ((unsigned)d >= 10U) {
+ d = (*p - 'a');
+ if ((unsigned)d >= 6U)
+ d = (*p - 'A');
+ if ((unsigned)d >= 6U)
+ break;
+ d += 10;
+ }
+ if (d >= base)
+ break;
+ val = val*base + d;
+ p++;
+ }
+ if (p == input)
+ return NULL;
+
+ *result = val;
+ return p;
+}
+
+static const char*
+parse_decimal(const char* input, const char* limit, int* result)
+{
+ return parse_number(input, limit, 10, result);
+}
+
+#ifdef __arm__
+static const char*
+parse_hexadecimal(const char* input, const char* limit, int* result)
+{
+ return parse_number(input, limit, 16, result);
+}
+#endif /* __arm__ */
+
+/* This small data type is used to represent a CPU list / mask, as read
+ * from sysfs on Linux. See http://www.kernel.org/doc/Documentation/cputopology.txt
+ *
+ * For now, we don't expect more than 32 cores on mobile devices, so keep
+ * everything simple.
+ */
+typedef struct {
+ uint32_t mask;
+} CpuList;
+
+static __inline__ void
+cpulist_init(CpuList* list) {
+ list->mask = 0;
+}
+
+static __inline__ void
+cpulist_and(CpuList* list1, CpuList* list2) {
+ list1->mask &= list2->mask;
+}
+
+static __inline__ void
+cpulist_set(CpuList* list, int index) {
+ if ((unsigned)index < 32) {
+ list->mask |= (uint32_t)(1U << index);
+ }
+}
+
+static __inline__ int
+cpulist_count(CpuList* list) {
+ return __builtin_popcount(list->mask);
+}
+
+/* Parse a textual list of cpus and store the result inside a CpuList object.
+ * Input format is the following:
+ * - comma-separated list of items (no spaces)
+ * - each item is either a single decimal number (cpu index), or a range made
+ * of two numbers separated by a single dash (-). Ranges are inclusive.
+ *
+ * Examples: 0
+ * 2,4-127,128-143
+ * 0-1
+ */
+static void
+cpulist_parse(CpuList* list, const char* line, int line_len)
+{
+ const char* p = line;
+ const char* end = p + line_len;
+ const char* q;
+
+ /* NOTE: the input line coming from sysfs typically contains a
+ * trailing newline, so take care of it in the code below
+ */
+ while (p < end && *p != '\n')
+ {
+ int val, start_value, end_value;
+
+ /* Find the end of current item, and put it into 'q' */
+ q = memchr(p, ',', end-p);
+ if (q == NULL) {
+ q = end;
+ }
+
+ /* Get first value */
+ p = parse_decimal(p, q, &start_value);
+ if (p == NULL)
+ goto BAD_FORMAT;
+
+ end_value = start_value;
+
+ /* If we're not at the end of the item, expect a dash and
+ * and integer; extract end value.
+ */
+ if (p < q && *p == '-') {
+ p = parse_decimal(p+1, q, &end_value);
+ if (p == NULL)
+ goto BAD_FORMAT;
+ }
+
+ /* Set bits CPU list bits */
+ for (val = start_value; val <= end_value; val++) {
+ cpulist_set(list, val);
+ }
+
+ /* Jump to next item */
+ p = q;
+ if (p < end)
+ p++;
+ }
+
+BAD_FORMAT:
+ ;
+}
+
+/* Read a CPU list from one sysfs file */
+static void
+cpulist_read_from(CpuList* list, const char* filename)
+{
+ char file[64];
+ int filelen;
+
+ cpulist_init(list);
+
+ filelen = read_file(filename, file, sizeof file);
+ if (filelen < 0) {
+ D("Could not read %s: %s\n", filename, strerror(errno));
+ return;
+ }
+
+ cpulist_parse(list, file, filelen);
+}
+#if defined(__aarch64__)
+// see <uapi/asm/hwcap.h> kernel header
+#define HWCAP_FP (1 << 0)
+#define HWCAP_ASIMD (1 << 1)
+#define HWCAP_AES (1 << 3)
+#define HWCAP_PMULL (1 << 4)
+#define HWCAP_SHA1 (1 << 5)
+#define HWCAP_SHA2 (1 << 6)
+#define HWCAP_CRC32 (1 << 7)
+#endif
+
+#if defined(__arm__)
+
+// See <asm/hwcap.h> kernel header.
+#define HWCAP_VFP (1 << 6)
+#define HWCAP_IWMMXT (1 << 9)
+#define HWCAP_NEON (1 << 12)
+#define HWCAP_VFPv3 (1 << 13)
+#define HWCAP_VFPv3D16 (1 << 14)
+#define HWCAP_VFPv4 (1 << 16)
+#define HWCAP_IDIVA (1 << 17)
+#define HWCAP_IDIVT (1 << 18)
+
+// see <uapi/asm/hwcap.h> kernel header
+#define HWCAP2_AES (1 << 0)
+#define HWCAP2_PMULL (1 << 1)
+#define HWCAP2_SHA1 (1 << 2)
+#define HWCAP2_SHA2 (1 << 3)
+#define HWCAP2_CRC32 (1 << 4)
+
+// This is the list of 32-bit ARMv7 optional features that are _always_
+// supported by ARMv8 CPUs, as mandated by the ARM Architecture Reference
+// Manual.
+#define HWCAP_SET_FOR_ARMV8 \
+ ( HWCAP_VFP | \
+ HWCAP_NEON | \
+ HWCAP_VFPv3 | \
+ HWCAP_VFPv4 | \
+ HWCAP_IDIVA | \
+ HWCAP_IDIVT )
+#endif
+
+#if defined(__mips__)
+// see <uapi/asm/hwcap.h> kernel header
+#define HWCAP_MIPS_R6 (1 << 0)
+#define HWCAP_MIPS_MSA (1 << 1)
+#endif
+
+#if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
+
+#define AT_HWCAP 16
+#define AT_HWCAP2 26
+
+// Probe the system's C library for a 'getauxval' function and call it if
+// it exits, or return 0 for failure. This function is available since API
+// level 20.
+//
+// This code does *NOT* check for '__ANDROID_API__ >= 20' to support the
+// edge case where some NDK developers use headers for a platform that is
+// newer than the one really targetted by their application.
+// This is typically done to use newer native APIs only when running on more
+// recent Android versions, and requires careful symbol management.
+//
+// Note that getauxval() can't really be re-implemented here, because
+// its implementation does not parse /proc/self/auxv. Instead it depends
+// on values that are passed by the kernel at process-init time to the
+// C runtime initialization layer.
+static uint32_t
+get_elf_hwcap_from_getauxval(int hwcap_type) {
+ typedef unsigned long getauxval_func_t(unsigned long);
+
+ dlerror();
+ void* libc_handle = dlopen("libc.so", RTLD_NOW);
+ if (!libc_handle) {
+ D("Could not dlopen() C library: %s\n", dlerror());
+ return 0;
+ }
+
+ uint32_t ret = 0;
+ getauxval_func_t* func = (getauxval_func_t*)
+ dlsym(libc_handle, "getauxval");
+ if (!func) {
+ D("Could not find getauxval() in C library\n");
+ } else {
+ // Note: getauxval() returns 0 on failure. Doesn't touch errno.
+ ret = (uint32_t)(*func)(hwcap_type);
+ }
+ dlclose(libc_handle);
+ return ret;
+}
+#endif
+
+#if defined(__arm__)
+// Parse /proc/self/auxv to extract the ELF HW capabilities bitmap for the
+// current CPU. Note that this file is not accessible from regular
+// application processes on some Android platform releases.
+// On success, return new ELF hwcaps, or 0 on failure.
+static uint32_t
+get_elf_hwcap_from_proc_self_auxv(void) {
+ const char filepath[] = "/proc/self/auxv";
+ int fd = TEMP_FAILURE_RETRY(open(filepath, O_RDONLY));
+ if (fd < 0) {
+ D("Could not open %s: %s\n", filepath, strerror(errno));
+ return 0;
+ }
+
+ struct { uint32_t tag; uint32_t value; } entry;
+
+ uint32_t result = 0;
+ for (;;) {
+ int ret = TEMP_FAILURE_RETRY(read(fd, (char*)&entry, sizeof entry));
+ if (ret < 0) {
+ D("Error while reading %s: %s\n", filepath, strerror(errno));
+ break;
+ }
+ // Detect end of list.
+ if (ret == 0 || (entry.tag == 0 && entry.value == 0))
+ break;
+ if (entry.tag == AT_HWCAP) {
+ result = entry.value;
+ break;
+ }
+ }
+ close(fd);
+ return result;
+}
+
+/* Compute the ELF HWCAP flags from the content of /proc/cpuinfo.
+ * This works by parsing the 'Features' line, which lists which optional
+ * features the device's CPU supports, on top of its reference
+ * architecture.
+ */
+static uint32_t
+get_elf_hwcap_from_proc_cpuinfo(const char* cpuinfo, int cpuinfo_len) {
+ uint32_t hwcaps = 0;
+ long architecture = 0;
+ char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture");
+ if (cpuArch) {
+ architecture = strtol(cpuArch, NULL, 10);
+ free(cpuArch);
+
+ if (architecture >= 8L) {
+ // This is a 32-bit ARM binary running on a 64-bit ARM64 kernel.
+ // The 'Features' line only lists the optional features that the
+ // device's CPU supports, compared to its reference architecture
+ // which are of no use for this process.
+ D("Faking 32-bit ARM HWCaps on ARMv%ld CPU\n", architecture);
+ return HWCAP_SET_FOR_ARMV8;
+ }
+ }
+
+ char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features");
+ if (cpuFeatures != NULL) {
+ D("Found cpuFeatures = '%s'\n", cpuFeatures);
+
+ if (has_list_item(cpuFeatures, "vfp"))
+ hwcaps |= HWCAP_VFP;
+ if (has_list_item(cpuFeatures, "vfpv3"))
+ hwcaps |= HWCAP_VFPv3;
+ if (has_list_item(cpuFeatures, "vfpv3d16"))
+ hwcaps |= HWCAP_VFPv3D16;
+ if (has_list_item(cpuFeatures, "vfpv4"))
+ hwcaps |= HWCAP_VFPv4;
+ if (has_list_item(cpuFeatures, "neon"))
+ hwcaps |= HWCAP_NEON;
+ if (has_list_item(cpuFeatures, "idiva"))
+ hwcaps |= HWCAP_IDIVA;
+ if (has_list_item(cpuFeatures, "idivt"))
+ hwcaps |= HWCAP_IDIVT;
+ if (has_list_item(cpuFeatures, "idiv"))
+ hwcaps |= HWCAP_IDIVA | HWCAP_IDIVT;
+ if (has_list_item(cpuFeatures, "iwmmxt"))
+ hwcaps |= HWCAP_IWMMXT;
+
+ free(cpuFeatures);
+ }
+ return hwcaps;
+}
+#endif /* __arm__ */
+
+/* Return the number of cpus present on a given device.
+ *
+ * To handle all weird kernel configurations, we need to compute the
+ * intersection of the 'present' and 'possible' CPU lists and count
+ * the result.
+ */
+static int
+get_cpu_count(void)
+{
+ CpuList cpus_present[1];
+ CpuList cpus_possible[1];
+
+ cpulist_read_from(cpus_present, "/sys/devices/system/cpu/present");
+ cpulist_read_from(cpus_possible, "/sys/devices/system/cpu/possible");
+
+ /* Compute the intersection of both sets to get the actual number of
+ * CPU cores that can be used on this device by the kernel.
+ */
+ cpulist_and(cpus_present, cpus_possible);
+
+ return cpulist_count(cpus_present);
+}
+
+static void
+android_cpuInitFamily(void)
+{
+#if defined(__arm__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_ARM;
+#elif defined(__i386__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_X86;
+#elif defined(__mips64)
+/* Needs to be before __mips__ since the compiler defines both */
+ g_cpuFamily = ANDROID_CPU_FAMILY_MIPS64;
+#elif defined(__mips__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_MIPS;
+#elif defined(__aarch64__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_ARM64;
+#elif defined(__x86_64__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_X86_64;
+#else
+ g_cpuFamily = ANDROID_CPU_FAMILY_UNKNOWN;
+#endif
+}
+
+static void
+android_cpuInit(void)
+{
+ char* cpuinfo = NULL;
+ int cpuinfo_len;
+
+ android_cpuInitFamily();
+
+ g_cpuFeatures = 0;
+ g_cpuCount = 1;
+ g_inited = 1;
+
+ cpuinfo_len = get_file_size("/proc/cpuinfo");
+ if (cpuinfo_len < 0) {
+ D("cpuinfo_len cannot be computed!");
+ return;
+ }
+ cpuinfo = malloc(cpuinfo_len);
+ if (cpuinfo == NULL) {
+ D("cpuinfo buffer could not be allocated");
+ return;
+ }
+ cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, cpuinfo_len);
+ D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len,
+ cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo);
+
+ if (cpuinfo_len < 0) /* should not happen */ {
+ free(cpuinfo);
+ return;
+ }
+
+ /* Count the CPU cores, the value may be 0 for single-core CPUs */
+ g_cpuCount = get_cpu_count();
+ if (g_cpuCount == 0) {
+ g_cpuCount = 1;
+ }
+
+ D("found cpuCount = %d\n", g_cpuCount);
+
+#ifdef __arm__
+ {
+ /* Extract architecture from the "CPU Architecture" field.
+ * The list is well-known, unlike the the output of
+ * the 'Processor' field which can vary greatly.
+ *
+ * See the definition of the 'proc_arch' array in
+ * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in
+ * same file.
+ */
+ char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture");
+
+ if (cpuArch != NULL) {
+ char* end;
+ long archNumber;
+ int hasARMv7 = 0;
+
+ D("found cpuArch = '%s'\n", cpuArch);
+
+ /* read the initial decimal number, ignore the rest */
+ archNumber = strtol(cpuArch, &end, 10);
+
+ /* Note that ARMv8 is upwards compatible with ARMv7. */
+ if (end > cpuArch && archNumber >= 7) {
+ hasARMv7 = 1;
+ }
+
+ /* Unfortunately, it seems that certain ARMv6-based CPUs
+ * report an incorrect architecture number of 7!
+ *
+ * See http://code.google.com/p/android/issues/detail?id=10812
+ *
+ * We try to correct this by looking at the 'elf_format'
+ * field reported by the 'Processor' field, which is of the
+ * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
+ * an ARMv6-one.
+ */
+ if (hasARMv7) {
+ char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len,
+ "Processor");
+ if (cpuProc != NULL) {
+ D("found cpuProc = '%s'\n", cpuProc);
+ if (has_list_item(cpuProc, "(v6l)")) {
+ D("CPU processor and architecture mismatch!!\n");
+ hasARMv7 = 0;
+ }
+ free(cpuProc);
+ }
+ }
+
+ if (hasARMv7) {
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7;
+ }
+
+ /* The LDREX / STREX instructions are available from ARMv6 */
+ if (archNumber >= 6) {
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX;
+ }
+
+ free(cpuArch);
+ }
+
+ /* Extract the list of CPU features from ELF hwcaps */
+ uint32_t hwcaps = 0;
+ hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP);
+ if (!hwcaps) {
+ D("Parsing /proc/self/auxv to extract ELF hwcaps!\n");
+ hwcaps = get_elf_hwcap_from_proc_self_auxv();
+ }
+ if (!hwcaps) {
+ // Parsing /proc/self/auxv will fail from regular application
+ // processes on some Android platform versions, when this happens
+ // parse proc/cpuinfo instead.
+ D("Parsing /proc/cpuinfo to extract ELF hwcaps!\n");
+ hwcaps = get_elf_hwcap_from_proc_cpuinfo(cpuinfo, cpuinfo_len);
+ }
+
+ if (hwcaps != 0) {
+ int has_vfp = (hwcaps & HWCAP_VFP);
+ int has_vfpv3 = (hwcaps & HWCAP_VFPv3);
+ int has_vfpv3d16 = (hwcaps & HWCAP_VFPv3D16);
+ int has_vfpv4 = (hwcaps & HWCAP_VFPv4);
+ int has_neon = (hwcaps & HWCAP_NEON);
+ int has_idiva = (hwcaps & HWCAP_IDIVA);
+ int has_idivt = (hwcaps & HWCAP_IDIVT);
+ int has_iwmmxt = (hwcaps & HWCAP_IWMMXT);
+
+ // The kernel does a poor job at ensuring consistency when
+ // describing CPU features. So lots of guessing is needed.
+
+ // 'vfpv4' implies VFPv3|VFP_FMA|FP16
+ if (has_vfpv4)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 |
+ ANDROID_CPU_ARM_FEATURE_VFP_FP16 |
+ ANDROID_CPU_ARM_FEATURE_VFP_FMA;
+
+ // 'vfpv3' or 'vfpv3d16' imply VFPv3. Note that unlike GCC,
+ // a value of 'vfpv3' doesn't necessarily mean that the D32
+ // feature is present, so be conservative. All CPUs in the
+ // field that support D32 also support NEON, so this should
+ // not be a problem in practice.
+ if (has_vfpv3 || has_vfpv3d16)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+
+ // 'vfp' is super ambiguous. Depending on the kernel, it can
+ // either mean VFPv2 or VFPv3. Make it depend on ARMv7.
+ if (has_vfp) {
+ if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_ARMv7)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+ else
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
+ }
+
+ // Neon implies VFPv3|D32, and if vfpv4 is detected, NEON_FMA
+ if (has_neon) {
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 |
+ ANDROID_CPU_ARM_FEATURE_NEON |
+ ANDROID_CPU_ARM_FEATURE_VFP_D32;
+ if (has_vfpv4)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
+ }
+
+ // VFPv3 implies VFPv2 and ARMv7
+ if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_VFPv3)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2 |
+ ANDROID_CPU_ARM_FEATURE_ARMv7;
+
+ if (has_idiva)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
+ if (has_idivt)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2;
+
+ if (has_iwmmxt)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt;
+ }
+
+ /* Extract the list of CPU features from ELF hwcaps2 */
+ uint32_t hwcaps2 = 0;
+ hwcaps2 = get_elf_hwcap_from_getauxval(AT_HWCAP2);
+ if (hwcaps2 != 0) {
+ int has_aes = (hwcaps2 & HWCAP2_AES);
+ int has_pmull = (hwcaps2 & HWCAP2_PMULL);
+ int has_sha1 = (hwcaps2 & HWCAP2_SHA1);
+ int has_sha2 = (hwcaps2 & HWCAP2_SHA2);
+ int has_crc32 = (hwcaps2 & HWCAP2_CRC32);
+
+ if (has_aes)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_AES;
+ if (has_pmull)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_PMULL;
+ if (has_sha1)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA1;
+ if (has_sha2)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA2;
+ if (has_crc32)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32;
+ }
+ /* Extract the cpuid value from various fields */
+ // The CPUID value is broken up in several entries in /proc/cpuinfo.
+ // This table is used to rebuild it from the entries.
+ static const struct CpuIdEntry {
+ const char* field;
+ char format;
+ char bit_lshift;
+ char bit_length;
+ } cpu_id_entries[] = {
+ { "CPU implementer", 'x', 24, 8 },
+ { "CPU variant", 'x', 20, 4 },
+ { "CPU part", 'x', 4, 12 },
+ { "CPU revision", 'd', 0, 4 },
+ };
+ size_t i;
+ D("Parsing /proc/cpuinfo to recover CPUID\n");
+ for (i = 0;
+ i < sizeof(cpu_id_entries)/sizeof(cpu_id_entries[0]);
+ ++i) {
+ const struct CpuIdEntry* entry = &cpu_id_entries[i];
+ char* value = extract_cpuinfo_field(cpuinfo,
+ cpuinfo_len,
+ entry->field);
+ if (value == NULL)
+ continue;
+
+ D("field=%s value='%s'\n", entry->field, value);
+ char* value_end = value + strlen(value);
+ int val = 0;
+ const char* start = value;
+ const char* p;
+ if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
+ start += 2;
+ p = parse_hexadecimal(start, value_end, &val);
+ } else if (entry->format == 'x')
+ p = parse_hexadecimal(value, value_end, &val);
+ else
+ p = parse_decimal(value, value_end, &val);
+
+ if (p > (const char*)start) {
+ val &= ((1 << entry->bit_length)-1);
+ val <<= entry->bit_lshift;
+ g_cpuIdArm |= (uint32_t) val;
+ }
+
+ free(value);
+ }
+
+ // Handle kernel configuration bugs that prevent the correct
+ // reporting of CPU features.
+ static const struct CpuFix {
+ uint32_t cpuid;
+ uint64_t or_flags;
+ } cpu_fixes[] = {
+ /* The Nexus 4 (Qualcomm Krait) kernel configuration
+ * forgets to report IDIV support. */
+ { 0x510006f2, ANDROID_CPU_ARM_FEATURE_IDIV_ARM |
+ ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 },
+ { 0x510006f3, ANDROID_CPU_ARM_FEATURE_IDIV_ARM |
+ ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 },
+ };
+ size_t n;
+ for (n = 0; n < sizeof(cpu_fixes)/sizeof(cpu_fixes[0]); ++n) {
+ const struct CpuFix* entry = &cpu_fixes[n];
+
+ if (g_cpuIdArm == entry->cpuid)
+ g_cpuFeatures |= entry->or_flags;
+ }
+
+ // Special case: The emulator-specific Android 4.2 kernel fails
+ // to report support for the 32-bit ARM IDIV instruction.
+ // Technically, this is a feature of the virtual CPU implemented
+ // by the emulator. Note that it could also support Thumb IDIV
+ // in the future, and this will have to be slightly updated.
+ char* hardware = extract_cpuinfo_field(cpuinfo,
+ cpuinfo_len,
+ "Hardware");
+ if (hardware) {
+ if (!strcmp(hardware, "Goldfish") &&
+ g_cpuIdArm == 0x4100c080 &&
+ (g_cpuFamily & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
+ }
+ free(hardware);
+ }
+ }
+#endif /* __arm__ */
+#ifdef __aarch64__
+ {
+ /* Extract the list of CPU features from ELF hwcaps */
+ uint32_t hwcaps = 0;
+ hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP);
+ if (hwcaps != 0) {
+ int has_fp = (hwcaps & HWCAP_FP);
+ int has_asimd = (hwcaps & HWCAP_ASIMD);
+ int has_aes = (hwcaps & HWCAP_AES);
+ int has_pmull = (hwcaps & HWCAP_PMULL);
+ int has_sha1 = (hwcaps & HWCAP_SHA1);
+ int has_sha2 = (hwcaps & HWCAP_SHA2);
+ int has_crc32 = (hwcaps & HWCAP_CRC32);
+
+ if(has_fp == 0) {
+ D("ERROR: Floating-point unit missing, but is required by Android on AArch64 CPUs\n");
+ }
+ if(has_asimd == 0) {
+ D("ERROR: ASIMD unit missing, but is required by Android on AArch64 CPUs\n");
+ }
+
+ if (has_fp)
+ g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_FP;
+ if (has_asimd)
+ g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_ASIMD;
+ if (has_aes)
+ g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_AES;
+ if (has_pmull)
+ g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_PMULL;
+ if (has_sha1)
+ g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA1;
+ if (has_sha2)
+ g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA2;
+ if (has_crc32)
+ g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_CRC32;
+ }
+ }
+#endif /* __aarch64__ */
+
+#if defined(__i386__) || defined(__x86_64__)
+ int regs[4];
+
+/* According to http://en.wikipedia.org/wiki/CPUID */
+#define VENDOR_INTEL_b 0x756e6547
+#define VENDOR_INTEL_c 0x6c65746e
+#define VENDOR_INTEL_d 0x49656e69
+
+ x86_cpuid(0, regs);
+ int vendorIsIntel = (regs[1] == VENDOR_INTEL_b &&
+ regs[2] == VENDOR_INTEL_c &&
+ regs[3] == VENDOR_INTEL_d);
+
+ x86_cpuid(1, regs);
+ if ((regs[2] & (1 << 9)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3;
+ }
+ if ((regs[2] & (1 << 23)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT;
+ }
+ if ((regs[2] & (1 << 19)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_1;
+ }
+ if ((regs[2] & (1 << 20)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_2;
+ }
+ if (vendorIsIntel && (regs[2] & (1 << 22)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE;
+ }
+ if ((regs[2] & (1 << 25)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AES_NI;
+ }
+ if ((regs[2] & (1 << 28)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX;
+ }
+ if ((regs[2] & (1 << 30)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_RDRAND;
+ }
+
+ x86_cpuid(7, regs);
+ if ((regs[1] & (1 << 5)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX2;
+ }
+ if ((regs[1] & (1 << 29)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SHA_NI;
+ }
+
+
+#endif
+#if defined( __mips__)
+ { /* MIPS and MIPS64 */
+ /* Extract the list of CPU features from ELF hwcaps */
+ uint32_t hwcaps = 0;
+ hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP);
+ if (hwcaps != 0) {
+ int has_r6 = (hwcaps & HWCAP_MIPS_R6);
+ int has_msa = (hwcaps & HWCAP_MIPS_MSA);
+ if (has_r6)
+ g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_R6;
+ if (has_msa)
+ g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_MSA;
+ }
+ }
+#endif /* __mips__ */
+
+ free(cpuinfo);
+}
+
+
+AndroidCpuFamily
+android_getCpuFamily(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuFamily;
+}
+
+
+uint64_t
+android_getCpuFeatures(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuFeatures;
+}
+
+
+int
+android_getCpuCount(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuCount;
+}
+
+static void
+android_cpuInitDummy(void)
+{
+ g_inited = 1;
+}
+
+int
+android_setCpu(int cpu_count, uint64_t cpu_features)
+{
+ /* Fail if the library was already initialized. */
+ if (g_inited)
+ return 0;
+
+ android_cpuInitFamily();
+ g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count);
+ g_cpuFeatures = cpu_features;
+ pthread_once(&g_once, android_cpuInitDummy);
+
+ return 1;
+}
+
+#ifdef __arm__
+uint32_t
+android_getCpuIdArm(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuIdArm;
+}
+
+int
+android_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id)
+{
+ if (!android_setCpu(cpu_count, cpu_features))
+ return 0;
+
+ g_cpuIdArm = cpu_id;
+ return 1;
+}
+#endif /* __arm__ */
+
+/*
+ * Technical note: Making sense of ARM's FPU architecture versions.
+ *
+ * FPA was ARM's first attempt at an FPU architecture. There is no Android
+ * device that actually uses it since this technology was already obsolete
+ * when the project started. If you see references to FPA instructions
+ * somewhere, you can be sure that this doesn't apply to Android at all.
+ *
+ * FPA was followed by "VFP", soon renamed "VFPv1" due to the emergence of
+ * new versions / additions to it. ARM considers this obsolete right now,
+ * and no known Android device implements it either.
+ *
+ * VFPv2 added a few instructions to VFPv1, and is an *optional* extension
+ * supported by some ARMv5TE, ARMv6 and ARMv6T2 CPUs. Note that a device
+ * supporting the 'armeabi' ABI doesn't necessarily support these.
+ *
+ * VFPv3-D16 adds a few instructions on top of VFPv2 and is typically used
+ * on ARMv7-A CPUs which implement a FPU. Note that it is also mandated
+ * by the Android 'armeabi-v7a' ABI. The -D16 suffix in its name means
+ * that it provides 16 double-precision FPU registers (d0-d15) and 32
+ * single-precision ones (s0-s31) which happen to be mapped to the same
+ * register banks.
+ *
+ * VFPv3-D32 is the name of an extension to VFPv3-D16 that provides 16
+ * additional double precision registers (d16-d31). Note that there are
+ * still only 32 single precision registers.
+ *
+ * VFPv3xD is a *subset* of VFPv3-D16 that only provides single-precision
+ * registers. It is only used on ARMv7-M (i.e. on micro-controllers) which
+ * are not supported by Android. Note that it is not compatible with VFPv2.
+ *
+ * NOTE: The term 'VFPv3' usually designate either VFPv3-D16 or VFPv3-D32
+ * depending on context. For example GCC uses it for VFPv3-D32, but
+ * the Linux kernel code uses it for VFPv3-D16 (especially in
+ * /proc/cpuinfo). Always try to use the full designation when
+ * possible.
+ *
+ * NEON, a.k.a. "ARM Advanced SIMD" is an extension that provides
+ * instructions to perform parallel computations on vectors of 8, 16,
+ * 32, 64 and 128 bit quantities. NEON requires VFPv32-D32 since all
+ * NEON registers are also mapped to the same register banks.
+ *
+ * VFPv4-D16, adds a few instructions on top of VFPv3-D16 in order to
+ * perform fused multiply-accumulate on VFP registers, as well as
+ * half-precision (16-bit) conversion operations.
+ *
+ * VFPv4-D32 is VFPv4-D16 with 32, instead of 16, FPU double precision
+ * registers.
+ *
+ * VPFv4-NEON is VFPv4-D32 with NEON instructions. It also adds fused
+ * multiply-accumulate instructions that work on the NEON registers.
+ *
+ * NOTE: Similarly, "VFPv4" might either reference VFPv4-D16 or VFPv4-D32
+ * depending on context.
+ *
+ * The following information was determined by scanning the binutils-2.22
+ * sources:
+ *
+ * Basic VFP instruction subsets:
+ *
+ * #define FPU_VFP_EXT_V1xD 0x08000000 // Base VFP instruction set.
+ * #define FPU_VFP_EXT_V1 0x04000000 // Double-precision insns.
+ * #define FPU_VFP_EXT_V2 0x02000000 // ARM10E VFPr1.
+ * #define FPU_VFP_EXT_V3xD 0x01000000 // VFPv3 single-precision.
+ * #define FPU_VFP_EXT_V3 0x00800000 // VFPv3 double-precision.
+ * #define FPU_NEON_EXT_V1 0x00400000 // Neon (SIMD) insns.
+ * #define FPU_VFP_EXT_D32 0x00200000 // Registers D16-D31.
+ * #define FPU_VFP_EXT_FP16 0x00100000 // Half-precision extensions.
+ * #define FPU_NEON_EXT_FMA 0x00080000 // Neon fused multiply-add
+ * #define FPU_VFP_EXT_FMA 0x00040000 // VFP fused multiply-add
+ *
+ * FPU types (excluding NEON)
+ *
+ * FPU_VFP_V1xD (EXT_V1xD)
+ * |
+ * +--------------------------+
+ * | |
+ * FPU_VFP_V1 (+EXT_V1) FPU_VFP_V3xD (+EXT_V2+EXT_V3xD)
+ * | |
+ * | |
+ * FPU_VFP_V2 (+EXT_V2) FPU_VFP_V4_SP_D16 (+EXT_FP16+EXT_FMA)
+ * |
+ * FPU_VFP_V3D16 (+EXT_Vx3D+EXT_V3)
+ * |
+ * +--------------------------+
+ * | |
+ * FPU_VFP_V3 (+EXT_D32) FPU_VFP_V4D16 (+EXT_FP16+EXT_FMA)
+ * | |
+ * | FPU_VFP_V4 (+EXT_D32)
+ * |
+ * FPU_VFP_HARD (+EXT_FMA+NEON_EXT_FMA)
+ *
+ * VFP architectures:
+ *
+ * ARCH_VFP_V1xD (EXT_V1xD)
+ * |
+ * +------------------+
+ * | |
+ * | ARCH_VFP_V3xD (+EXT_V2+EXT_V3xD)
+ * | |
+ * | ARCH_VFP_V3xD_FP16 (+EXT_FP16)
+ * | |
+ * | ARCH_VFP_V4_SP_D16 (+EXT_FMA)
+ * |
+ * ARCH_VFP_V1 (+EXT_V1)
+ * |
+ * ARCH_VFP_V2 (+EXT_V2)
+ * |
+ * ARCH_VFP_V3D16 (+EXT_V3xD+EXT_V3)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V3D16_FP16 (+EXT_FP16)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V4_D16 (+EXT_FP16+EXT_FMA)
+ * | |
+ * | ARCH_VFP_V4 (+EXT_D32)
+ * | |
+ * | ARCH_NEON_VFP_V4 (+EXT_NEON+EXT_NEON_FMA)
+ * |
+ * ARCH_VFP_V3 (+EXT_D32)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V3_FP16 (+EXT_FP16)
+ * |
+ * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON)
+ * |
+ * ARCH_NEON_FP16 (+EXT_FP16)
+ *
+ * -fpu=<name> values and their correspondance with FPU architectures above:
+ *
+ * {"vfp", FPU_ARCH_VFP_V2},
+ * {"vfp9", FPU_ARCH_VFP_V2},
+ * {"vfp3", FPU_ARCH_VFP_V3}, // For backwards compatbility.
+ * {"vfp10", FPU_ARCH_VFP_V2},
+ * {"vfp10-r0", FPU_ARCH_VFP_V1},
+ * {"vfpxd", FPU_ARCH_VFP_V1xD},
+ * {"vfpv2", FPU_ARCH_VFP_V2},
+ * {"vfpv3", FPU_ARCH_VFP_V3},
+ * {"vfpv3-fp16", FPU_ARCH_VFP_V3_FP16},
+ * {"vfpv3-d16", FPU_ARCH_VFP_V3D16},
+ * {"vfpv3-d16-fp16", FPU_ARCH_VFP_V3D16_FP16},
+ * {"vfpv3xd", FPU_ARCH_VFP_V3xD},
+ * {"vfpv3xd-fp16", FPU_ARCH_VFP_V3xD_FP16},
+ * {"neon", FPU_ARCH_VFP_V3_PLUS_NEON_V1},
+ * {"neon-fp16", FPU_ARCH_NEON_FP16},
+ * {"vfpv4", FPU_ARCH_VFP_V4},
+ * {"vfpv4-d16", FPU_ARCH_VFP_V4D16},
+ * {"fpv4-sp-d16", FPU_ARCH_VFP_V4_SP_D16},
+ * {"neon-vfpv4", FPU_ARCH_NEON_VFP_V4},
+ *
+ *
+ * Simplified diagram that only includes FPUs supported by Android:
+ * Only ARCH_VFP_V3D16 is actually mandated by the armeabi-v7a ABI,
+ * all others are optional and must be probed at runtime.
+ *
+ * ARCH_VFP_V3D16 (EXT_V1xD+EXT_V1+EXT_V2+EXT_V3xD+EXT_V3)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V3D16_FP16 (+EXT_FP16)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V4_D16 (+EXT_FP16+EXT_FMA)
+ * | |
+ * | ARCH_VFP_V4 (+EXT_D32)
+ * | |
+ * | ARCH_NEON_VFP_V4 (+EXT_NEON+EXT_NEON_FMA)
+ * |
+ * ARCH_VFP_V3 (+EXT_D32)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V3_FP16 (+EXT_FP16)
+ * |
+ * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON)
+ * |
+ * ARCH_NEON_FP16 (+EXT_FP16)
+ *
+ */
diff --git a/thirdparty/libvpx/third_party/android/cpu-features.h b/thirdparty/libvpx/third_party/android/cpu-features.h
new file mode 100644
index 0000000000..1e9724197a
--- /dev/null
+++ b/thirdparty/libvpx/third_party/android/cpu-features.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+#ifndef CPU_FEATURES_H
+#define CPU_FEATURES_H
+
+#include <sys/cdefs.h>
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+/* A list of valid values returned by android_getCpuFamily().
+ * They describe the CPU Architecture of the current process.
+ */
+typedef enum {
+ ANDROID_CPU_FAMILY_UNKNOWN = 0,
+ ANDROID_CPU_FAMILY_ARM,
+ ANDROID_CPU_FAMILY_X86,
+ ANDROID_CPU_FAMILY_MIPS,
+ ANDROID_CPU_FAMILY_ARM64,
+ ANDROID_CPU_FAMILY_X86_64,
+ ANDROID_CPU_FAMILY_MIPS64,
+
+ ANDROID_CPU_FAMILY_MAX /* do not remove */
+
+} AndroidCpuFamily;
+
+/* Return the CPU family of the current process.
+ *
+ * Note that this matches the bitness of the current process. I.e. when
+ * running a 32-bit binary on a 64-bit capable CPU, this will return the
+ * 32-bit CPU family value.
+ */
+extern AndroidCpuFamily android_getCpuFamily(void);
+
+/* Return a bitmap describing a set of optional CPU features that are
+ * supported by the current device's CPU. The exact bit-flags returned
+ * depend on the value returned by android_getCpuFamily(). See the
+ * documentation for the ANDROID_CPU_*_FEATURE_* flags below for details.
+ */
+extern uint64_t android_getCpuFeatures(void);
+
+/* The list of feature flags for ANDROID_CPU_FAMILY_ARM that can be
+ * recognized by the library (see note below for 64-bit ARM). Value details
+ * are:
+ *
+ * VFPv2:
+ * CPU supports the VFPv2 instruction set. Many, but not all, ARMv6 CPUs
+ * support these instructions. VFPv2 is a subset of VFPv3 so this will
+ * be set whenever VFPv3 is set too.
+ *
+ * ARMv7:
+ * CPU supports the ARMv7-A basic instruction set.
+ * This feature is mandated by the 'armeabi-v7a' ABI.
+ *
+ * VFPv3:
+ * CPU supports the VFPv3-D16 instruction set, providing hardware FPU
+ * support for single and double precision floating point registers.
+ * Note that only 16 FPU registers are available by default, unless
+ * the D32 bit is set too. This feature is also mandated by the
+ * 'armeabi-v7a' ABI.
+ *
+ * VFP_D32:
+ * CPU VFP optional extension that provides 32 FPU registers,
+ * instead of 16. Note that ARM mandates this feature is the 'NEON'
+ * feature is implemented by the CPU.
+ *
+ * NEON:
+ * CPU FPU supports "ARM Advanced SIMD" instructions, also known as
+ * NEON. Note that this mandates the VFP_D32 feature as well, per the
+ * ARM Architecture specification.
+ *
+ * VFP_FP16:
+ * Half-width floating precision VFP extension. If set, the CPU
+ * supports instructions to perform floating-point operations on
+ * 16-bit registers. This is part of the VFPv4 specification, but
+ * not mandated by any Android ABI.
+ *
+ * VFP_FMA:
+ * Fused multiply-accumulate VFP instructions extension. Also part of
+ * the VFPv4 specification, but not mandated by any Android ABI.
+ *
+ * NEON_FMA:
+ * Fused multiply-accumulate NEON instructions extension. Optional
+ * extension from the VFPv4 specification, but not mandated by any
+ * Android ABI.
+ *
+ * IDIV_ARM:
+ * Integer division available in ARM mode. Only available
+ * on recent CPUs (e.g. Cortex-A15).
+ *
+ * IDIV_THUMB2:
+ * Integer division available in Thumb-2 mode. Only available
+ * on recent CPUs (e.g. Cortex-A15).
+ *
+ * iWMMXt:
+ * Optional extension that adds MMX registers and operations to an
+ * ARM CPU. This is only available on a few XScale-based CPU designs
+ * sold by Marvell. Pretty rare in practice.
+ *
+ * AES:
+ * CPU supports AES instructions. These instructions are only
+ * available for 32-bit applications running on ARMv8 CPU.
+ *
+ * CRC32:
+ * CPU supports CRC32 instructions. These instructions are only
+ * available for 32-bit applications running on ARMv8 CPU.
+ *
+ * SHA2:
+ * CPU supports SHA2 instructions. These instructions are only
+ * available for 32-bit applications running on ARMv8 CPU.
+ *
+ * SHA1:
+ * CPU supports SHA1 instructions. These instructions are only
+ * available for 32-bit applications running on ARMv8 CPU.
+ *
+ * PMULL:
+ * CPU supports 64-bit PMULL and PMULL2 instructions. These
+ * instructions are only available for 32-bit applications
+ * running on ARMv8 CPU.
+ *
+ * If you want to tell the compiler to generate code that targets one of
+ * the feature set above, you should probably use one of the following
+ * flags (for more details, see technical note at the end of this file):
+ *
+ * -mfpu=vfp
+ * -mfpu=vfpv2
+ * These are equivalent and tell GCC to use VFPv2 instructions for
+ * floating-point operations. Use this if you want your code to
+ * run on *some* ARMv6 devices, and any ARMv7-A device supported
+ * by Android.
+ *
+ * Generated code requires VFPv2 feature.
+ *
+ * -mfpu=vfpv3-d16
+ * Tell GCC to use VFPv3 instructions (using only 16 FPU registers).
+ * This should be generic code that runs on any CPU that supports the
+ * 'armeabi-v7a' Android ABI. Note that no ARMv6 CPU supports this.
+ *
+ * Generated code requires VFPv3 feature.
+ *
+ * -mfpu=vfpv3
+ * Tell GCC to use VFPv3 instructions with 32 FPU registers.
+ * Generated code requires VFPv3|VFP_D32 features.
+ *
+ * -mfpu=neon
+ * Tell GCC to use VFPv3 instructions with 32 FPU registers, and
+ * also support NEON intrinsics (see <arm_neon.h>).
+ * Generated code requires VFPv3|VFP_D32|NEON features.
+ *
+ * -mfpu=vfpv4-d16
+ * Generated code requires VFPv3|VFP_FP16|VFP_FMA features.
+ *
+ * -mfpu=vfpv4
+ * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32 features.
+ *
+ * -mfpu=neon-vfpv4
+ * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32|NEON|NEON_FMA
+ * features.
+ *
+ * -mcpu=cortex-a7
+ * -mcpu=cortex-a15
+ * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32|
+ * NEON|NEON_FMA|IDIV_ARM|IDIV_THUMB2
+ * This flag implies -mfpu=neon-vfpv4.
+ *
+ * -mcpu=iwmmxt
+ * Allows the use of iWMMXt instrinsics with GCC.
+ *
+ * IMPORTANT NOTE: These flags should only be tested when
+ * android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM, i.e. this is a
+ * 32-bit process.
+ *
+ * When running a 64-bit ARM process on an ARMv8 CPU,
+ * android_getCpuFeatures() will return a different set of bitflags
+ */
+enum {
+ ANDROID_CPU_ARM_FEATURE_ARMv7 = (1 << 0),
+ ANDROID_CPU_ARM_FEATURE_VFPv3 = (1 << 1),
+ ANDROID_CPU_ARM_FEATURE_NEON = (1 << 2),
+ ANDROID_CPU_ARM_FEATURE_LDREX_STREX = (1 << 3),
+ ANDROID_CPU_ARM_FEATURE_VFPv2 = (1 << 4),
+ ANDROID_CPU_ARM_FEATURE_VFP_D32 = (1 << 5),
+ ANDROID_CPU_ARM_FEATURE_VFP_FP16 = (1 << 6),
+ ANDROID_CPU_ARM_FEATURE_VFP_FMA = (1 << 7),
+ ANDROID_CPU_ARM_FEATURE_NEON_FMA = (1 << 8),
+ ANDROID_CPU_ARM_FEATURE_IDIV_ARM = (1 << 9),
+ ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 = (1 << 10),
+ ANDROID_CPU_ARM_FEATURE_iWMMXt = (1 << 11),
+ ANDROID_CPU_ARM_FEATURE_AES = (1 << 12),
+ ANDROID_CPU_ARM_FEATURE_PMULL = (1 << 13),
+ ANDROID_CPU_ARM_FEATURE_SHA1 = (1 << 14),
+ ANDROID_CPU_ARM_FEATURE_SHA2 = (1 << 15),
+ ANDROID_CPU_ARM_FEATURE_CRC32 = (1 << 16),
+};
+
+/* The bit flags corresponding to the output of android_getCpuFeatures()
+ * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM64. Value details
+ * are:
+ *
+ * FP:
+ * CPU has Floating-point unit.
+ *
+ * ASIMD:
+ * CPU has Advanced SIMD unit.
+ *
+ * AES:
+ * CPU supports AES instructions.
+ *
+ * CRC32:
+ * CPU supports CRC32 instructions.
+ *
+ * SHA2:
+ * CPU supports SHA2 instructions.
+ *
+ * SHA1:
+ * CPU supports SHA1 instructions.
+ *
+ * PMULL:
+ * CPU supports 64-bit PMULL and PMULL2 instructions.
+ */
+enum {
+ ANDROID_CPU_ARM64_FEATURE_FP = (1 << 0),
+ ANDROID_CPU_ARM64_FEATURE_ASIMD = (1 << 1),
+ ANDROID_CPU_ARM64_FEATURE_AES = (1 << 2),
+ ANDROID_CPU_ARM64_FEATURE_PMULL = (1 << 3),
+ ANDROID_CPU_ARM64_FEATURE_SHA1 = (1 << 4),
+ ANDROID_CPU_ARM64_FEATURE_SHA2 = (1 << 5),
+ ANDROID_CPU_ARM64_FEATURE_CRC32 = (1 << 6),
+};
+
+/* The bit flags corresponding to the output of android_getCpuFeatures()
+ * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_X86 or
+ * ANDROID_CPU_FAMILY_X86_64.
+ */
+enum {
+ ANDROID_CPU_X86_FEATURE_SSSE3 = (1 << 0),
+ ANDROID_CPU_X86_FEATURE_POPCNT = (1 << 1),
+ ANDROID_CPU_X86_FEATURE_MOVBE = (1 << 2),
+ ANDROID_CPU_X86_FEATURE_SSE4_1 = (1 << 3),
+ ANDROID_CPU_X86_FEATURE_SSE4_2 = (1 << 4),
+ ANDROID_CPU_X86_FEATURE_AES_NI = (1 << 5),
+ ANDROID_CPU_X86_FEATURE_AVX = (1 << 6),
+ ANDROID_CPU_X86_FEATURE_RDRAND = (1 << 7),
+ ANDROID_CPU_X86_FEATURE_AVX2 = (1 << 8),
+ ANDROID_CPU_X86_FEATURE_SHA_NI = (1 << 9),
+};
+
+/* The bit flags corresponding to the output of android_getCpuFeatures()
+ * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_MIPS
+ * or ANDROID_CPU_FAMILY_MIPS64. Values are:
+ *
+ * R6:
+ * CPU executes MIPS Release 6 instructions natively, and
+ * supports obsoleted R1..R5 instructions only via kernel traps.
+ *
+ * MSA:
+ * CPU supports Mips SIMD Architecture instructions.
+ */
+enum {
+ ANDROID_CPU_MIPS_FEATURE_R6 = (1 << 0),
+ ANDROID_CPU_MIPS_FEATURE_MSA = (1 << 1),
+};
+
+
+/* Return the number of CPU cores detected on this device. */
+extern int android_getCpuCount(void);
+
+/* The following is used to force the CPU count and features
+ * mask in sandboxed processes. Under 4.1 and higher, these processes
+ * cannot access /proc, which is the only way to get information from
+ * the kernel about the current hardware (at least on ARM).
+ *
+ * It _must_ be called only once, and before any android_getCpuXXX
+ * function, any other case will fail.
+ *
+ * This function return 1 on success, and 0 on failure.
+ */
+extern int android_setCpu(int cpu_count,
+ uint64_t cpu_features);
+
+#ifdef __arm__
+/* Retrieve the ARM 32-bit CPUID value from the kernel.
+ * Note that this cannot work on sandboxed processes under 4.1 and
+ * higher, unless you called android_setCpuArm() before.
+ */
+extern uint32_t android_getCpuIdArm(void);
+
+/* An ARM-specific variant of android_setCpu() that also allows you
+ * to set the ARM CPUID field.
+ */
+extern int android_setCpuArm(int cpu_count,
+ uint64_t cpu_features,
+ uint32_t cpu_id);
+#endif
+
+__END_DECLS
+
+#endif /* CPU_FEATURES_H */
diff --git a/thirdparty/libwebp/src/dec/alphai_dec.h b/thirdparty/libwebp/src/dec/alphai_dec.h
index e0fa281a55..a64104abeb 100644
--- a/thirdparty/libwebp/src/dec/alphai_dec.h
+++ b/thirdparty/libwebp/src/dec/alphai_dec.h
@@ -51,4 +51,4 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec);
} // extern "C"
#endif
-#endif /* WEBP_DEC_ALPHAI_DEC_H_ */
+#endif // WEBP_DEC_ALPHAI_DEC_H_
diff --git a/thirdparty/libwebp/src/dec/buffer_dec.c b/thirdparty/libwebp/src/dec/buffer_dec.c
index 75eb3c40b4..3cd94eb4d9 100644
--- a/thirdparty/libwebp/src/dec/buffer_dec.c
+++ b/thirdparty/libwebp/src/dec/buffer_dec.c
@@ -74,7 +74,8 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
} else { // RGB checks
const WebPRGBABuffer* const buf = &buffer->u.RGBA;
const int stride = abs(buf->stride);
- const uint64_t size = MIN_BUFFER_SIZE(width, height, stride);
+ const uint64_t size =
+ MIN_BUFFER_SIZE(width * kModeBpp[mode], height, stride);
ok &= (size <= buf->size);
ok &= (stride >= width * kModeBpp[mode]);
ok &= (buf->rgba != NULL);
diff --git a/thirdparty/libwebp/src/dec/common_dec.h b/thirdparty/libwebp/src/dec/common_dec.h
index 9995f1a51a..b158550a80 100644
--- a/thirdparty/libwebp/src/dec/common_dec.h
+++ b/thirdparty/libwebp/src/dec/common_dec.h
@@ -51,4 +51,4 @@ enum { MB_FEATURE_TREE_PROBS = 3,
NUM_PROBAS = 11
};
-#endif // WEBP_DEC_COMMON_DEC_H_
+#endif // WEBP_DEC_COMMON_DEC_H_
diff --git a/thirdparty/libwebp/src/dec/frame_dec.c b/thirdparty/libwebp/src/dec/frame_dec.c
index a9d5430d00..bda9e1a6f6 100644
--- a/thirdparty/libwebp/src/dec/frame_dec.c
+++ b/thirdparty/libwebp/src/dec/frame_dec.c
@@ -338,7 +338,6 @@ void VP8InitDithering(const WebPDecoderOptions* const options,
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
VP8QuantMatrix* const dqm = &dec->dqm_[s];
if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) {
- // TODO(skal): should we specially dither more for uv_quant_ < 0?
const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_;
dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3;
}
@@ -669,15 +668,9 @@ int VP8GetThreadMethod(const WebPDecoderOptions* const options,
(void)height;
assert(headers == NULL || !headers->is_lossless);
#if defined(WEBP_USE_THREAD)
- if (width < MIN_WIDTH_FOR_THREADS) return 0;
- // TODO(skal): tune the heuristic further
-#if 0
- if (height < 2 * width) return 2;
+ if (width >= MIN_WIDTH_FOR_THREADS) return 2;
#endif
- return 2;
-#else // !WEBP_USE_THREAD
return 0;
-#endif
}
#undef MT_CACHE_LINES
diff --git a/thirdparty/libwebp/src/dec/idec_dec.c b/thirdparty/libwebp/src/dec/idec_dec.c
index a371ed7500..9bc9166808 100644
--- a/thirdparty/libwebp/src/dec/idec_dec.c
+++ b/thirdparty/libwebp/src/dec/idec_dec.c
@@ -140,10 +140,9 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
if (NeedCompressedAlpha(idec)) {
ALPHDecoder* const alph_dec = dec->alph_dec_;
dec->alpha_data_ += offset;
- if (alph_dec != NULL) {
+ if (alph_dec != NULL && alph_dec->vp8l_dec_ != NULL) {
if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) {
VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_;
- assert(alph_vp8l_dec != NULL);
assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN);
VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_,
dec->alpha_data_ + ALPHA_HEADER_LEN,
@@ -283,10 +282,8 @@ static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
if (idec->state_ == STATE_VP8_DATA) {
- VP8Io* const io = &idec->io_;
- if (io->teardown != NULL) {
- io->teardown(io);
- }
+ // Synchronize the thread, clean-up and check for errors.
+ VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
}
idec->state_ = STATE_ERROR;
return error;
@@ -451,7 +448,10 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
VP8Io* const io = &idec->io_;
- assert(dec->ready_);
+ // Make sure partition #0 has been read before, to set dec to ready_.
+ if (!dec->ready_) {
+ return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
+ }
for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) {
if (idec->last_mb_y_ != dec->mb_y_) {
if (!VP8ParseIntraModeRow(&dec->br_, dec)) {
@@ -473,6 +473,12 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
}
+ // Synchronize the threads.
+ if (dec->mt_method_ > 0) {
+ if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) {
+ return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
+ }
+ }
RestoreContext(&context, dec, token_br);
return VP8_STATUS_SUSPENDED;
}
@@ -491,6 +497,7 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
}
// Synchronize the thread and check for errors.
if (!VP8ExitCritical(dec, io)) {
+ idec->state_ = STATE_ERROR; // prevent re-entry in IDecError
return IDecError(idec, VP8_STATUS_USER_ABORT);
}
dec->ready_ = 0;
@@ -571,6 +578,10 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) {
status = DecodePartition0(idec);
}
if (idec->state_ == STATE_VP8_DATA) {
+ const VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
+ if (dec == NULL) {
+ return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder.
+ }
status = DecodeRemaining(idec);
}
if (idec->state_ == STATE_VP8L_HEADER) {
diff --git a/thirdparty/libwebp/src/dec/vp8_dec.h b/thirdparty/libwebp/src/dec/vp8_dec.h
index ca85b340cf..a05405df72 100644
--- a/thirdparty/libwebp/src/dec/vp8_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8_dec.h
@@ -182,4 +182,4 @@ WEBP_EXTERN int VP8LGetInfo(
} // extern "C"
#endif
-#endif /* WEBP_DEC_VP8_DEC_H_ */
+#endif // WEBP_DEC_VP8_DEC_H_
diff --git a/thirdparty/libwebp/src/dec/vp8i_dec.h b/thirdparty/libwebp/src/dec/vp8i_dec.h
index c929933e1c..e5e89df57d 100644
--- a/thirdparty/libwebp/src/dec/vp8i_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8i_dec.h
@@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 1
#define DEC_MIN_VERSION 0
-#define DEC_REV_VERSION 0
+#define DEC_REV_VERSION 1
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y),
@@ -316,4 +316,4 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
} // extern "C"
#endif
-#endif /* WEBP_DEC_VP8I_DEC_H_ */
+#endif // WEBP_DEC_VP8I_DEC_H_
diff --git a/thirdparty/libwebp/src/dec/vp8l_dec.c b/thirdparty/libwebp/src/dec/vp8l_dec.c
index 0570f53a77..333bb3e80d 100644
--- a/thirdparty/libwebp/src/dec/vp8l_dec.c
+++ b/thirdparty/libwebp/src/dec/vp8l_dec.c
@@ -362,12 +362,19 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL;
+ // When reading htrees, some might be unused, as the format allows it.
+ // We will still read them but put them in this htree_group_bogus.
+ HTreeGroup htree_group_bogus;
HuffmanCode* huffman_tables = NULL;
+ HuffmanCode* huffman_tables_bogus = NULL;
HuffmanCode* next = NULL;
int num_htree_groups = 1;
+ int num_htree_groups_max = 1;
int max_alphabet_size = 0;
int* code_lengths = NULL;
const int table_size = kTableSize[color_cache_bits];
+ int* mapping = NULL;
+ int ok = 0;
if (allow_recursion && VP8LReadBits(br, 1)) {
// use meta Huffman codes.
@@ -384,9 +391,41 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
// The huffman data is stored in red and green bytes.
const int group = (huffman_image[i] >> 8) & 0xffff;
huffman_image[i] = group;
- if (group >= num_htree_groups) {
- num_htree_groups = group + 1;
+ if (group >= num_htree_groups_max) {
+ num_htree_groups_max = group + 1;
+ }
+ }
+ // Check the validity of num_htree_groups_max. If it seems too big, use a
+ // smaller value for later. This will prevent big memory allocations to end
+ // up with a bad bitstream anyway.
+ // The value of 1000 is totally arbitrary. We know that num_htree_groups_max
+ // is smaller than (1 << 16) and should be smaller than the number of pixels
+ // (though the format allows it to be bigger).
+ if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) {
+ // Create a mapping from the used indices to the minimal set of used
+ // values [0, num_htree_groups)
+ mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping));
+ if (mapping == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ goto Error;
+ }
+ // -1 means a value is unmapped, and therefore unused in the Huffman
+ // image.
+ memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping));
+ for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) {
+ // Get the current mapping for the group and remap the Huffman image.
+ int* const mapped_group = &mapping[huffman_image[i]];
+ if (*mapped_group == -1) *mapped_group = num_htree_groups++;
+ huffman_image[i] = *mapped_group;
+ }
+ huffman_tables_bogus = (HuffmanCode*)WebPSafeMalloc(
+ table_size, sizeof(*huffman_tables_bogus));
+ if (huffman_tables_bogus == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ goto Error;
}
+ } else {
+ num_htree_groups = num_htree_groups_max;
}
}
@@ -403,11 +442,11 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
}
}
+ code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
+ sizeof(*code_lengths));
huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
sizeof(*huffman_tables));
htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
- code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
- sizeof(*code_lengths));
if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
@@ -415,28 +454,35 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
}
next = huffman_tables;
- for (i = 0; i < num_htree_groups; ++i) {
- HTreeGroup* const htree_group = &htree_groups[i];
+ for (i = 0; i < num_htree_groups_max; ++i) {
+ // If the index "i" is unused in the Huffman image, read the coefficients
+ // but store them to a bogus htree_group.
+ const int is_bogus = (mapping != NULL && mapping[i] == -1);
+ HTreeGroup* const htree_group =
+ is_bogus ? &htree_group_bogus :
+ &htree_groups[(mapping == NULL) ? i : mapping[i]];
HuffmanCode** const htrees = htree_group->htrees;
+ HuffmanCode* huffman_tables_i = is_bogus ? huffman_tables_bogus : next;
int size;
int total_size = 0;
int is_trivial_literal = 1;
int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
- htrees[j] = next;
+ htrees[j] = huffman_tables_i;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += 1 << color_cache_bits;
}
- size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next);
+ size =
+ ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables_i);
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
- is_trivial_literal = (next->bits == 0);
+ is_trivial_literal = (huffman_tables_i->bits == 0);
}
- total_size += next->bits;
- next += size;
+ total_size += huffman_tables_i->bits;
+ huffman_tables_i += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
@@ -448,38 +494,41 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
max_bits += local_max_bits;
}
}
+ if (!is_bogus) next = huffman_tables_i;
htree_group->is_trivial_literal = is_trivial_literal;
htree_group->is_trivial_code = 0;
if (is_trivial_literal) {
const int red = htrees[RED][0].value;
const int blue = htrees[BLUE][0].value;
const int alpha = htrees[ALPHA][0].value;
- htree_group->literal_arb =
- ((uint32_t)alpha << 24) | (red << 16) | blue;
+ htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
htree_group->is_trivial_code = 1;
htree_group->literal_arb |= htrees[GREEN][0].value << 8;
}
}
- htree_group->use_packed_table = !htree_group->is_trivial_code &&
- (max_bits < HUFFMAN_PACKED_BITS);
+ htree_group->use_packed_table =
+ !htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
if (htree_group->use_packed_table) BuildPackedTable(htree_group);
}
- WebPSafeFree(code_lengths);
+ ok = 1;
- // All OK. Finalize pointers and return.
+ // All OK. Finalize pointers.
hdr->huffman_image_ = huffman_image;
hdr->num_htree_groups_ = num_htree_groups;
hdr->htree_groups_ = htree_groups;
hdr->huffman_tables_ = huffman_tables;
- return 1;
Error:
WebPSafeFree(code_lengths);
- WebPSafeFree(huffman_image);
- WebPSafeFree(huffman_tables);
- VP8LHtreeGroupsFree(htree_groups);
- return 0;
+ WebPSafeFree(huffman_tables_bogus);
+ WebPSafeFree(mapping);
+ if (!ok) {
+ WebPSafeFree(huffman_image);
+ WebPSafeFree(huffman_tables);
+ VP8LHtreeGroupsFree(htree_groups);
+ }
+ return ok;
}
//------------------------------------------------------------------------------
@@ -884,7 +933,11 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
#endif
break;
case 2:
+#if !defined(WORDS_BIGENDIAN)
memcpy(&pattern, src, sizeof(uint16_t));
+#else
+ pattern = ((uint32_t)src[0] << 8) | src[1];
+#endif
#if defined(__arm__) || defined(_M_ARM)
pattern |= pattern << 16;
#elif defined(WEBP_USE_MIPS_DSP_R2)
@@ -1523,7 +1576,6 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
if (dec == NULL) return 0;
assert(alph_dec != NULL);
- alph_dec->vp8l_dec_ = dec;
dec->width_ = alph_dec->width_;
dec->height_ = alph_dec->height_;
@@ -1555,11 +1607,12 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
if (!ok) goto Err;
+ // Only set here, once we are sure it is valid (to avoid thread races).
+ alph_dec->vp8l_dec_ = dec;
return 1;
Err:
- VP8LDelete(alph_dec->vp8l_dec_);
- alph_dec->vp8l_dec_ = NULL;
+ VP8LDelete(dec);
return 0;
}
diff --git a/thirdparty/libwebp/src/dec/vp8li_dec.h b/thirdparty/libwebp/src/dec/vp8li_dec.h
index 8e500cf9ff..0a4d613f99 100644
--- a/thirdparty/libwebp/src/dec/vp8li_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8li_dec.h
@@ -132,4 +132,4 @@ void VP8LDelete(VP8LDecoder* const dec);
} // extern "C"
#endif
-#endif /* WEBP_DEC_VP8LI_DEC_H_ */
+#endif // WEBP_DEC_VP8LI_DEC_H_
diff --git a/thirdparty/libwebp/src/dec/webpi_dec.h b/thirdparty/libwebp/src/dec/webpi_dec.h
index c378ba6fc3..24baff5d27 100644
--- a/thirdparty/libwebp/src/dec/webpi_dec.h
+++ b/thirdparty/libwebp/src/dec/webpi_dec.h
@@ -130,4 +130,4 @@ int WebPAvoidSlowMemory(const WebPDecBuffer* const output,
} // extern "C"
#endif
-#endif /* WEBP_DEC_WEBPI_DEC_H_ */
+#endif // WEBP_DEC_WEBPI_DEC_H_
diff --git a/thirdparty/libwebp/src/demux/demux.c b/thirdparty/libwebp/src/demux/demux.c
index 684215e3de..a69c65b7cf 100644
--- a/thirdparty/libwebp/src/demux/demux.c
+++ b/thirdparty/libwebp/src/demux/demux.c
@@ -25,7 +25,7 @@
#define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 0
-#define DMUX_REV_VERSION 0
+#define DMUX_REV_VERSION 1
typedef struct {
size_t start_; // start location of the data
diff --git a/thirdparty/libwebp/src/dsp/dsp.h b/thirdparty/libwebp/src/dsp/dsp.h
index 4ab77a5130..fafc2d05d3 100644
--- a/thirdparty/libwebp/src/dsp/dsp.h
+++ b/thirdparty/libwebp/src/dsp/dsp.h
@@ -76,10 +76,6 @@ extern "C" {
#define WEBP_USE_SSE41
#endif
-#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2)
-#define WEBP_USE_AVX2
-#endif
-
// The intrinsics currently cause compiler errors with arm-nacl-gcc and the
// inline assembly would need to be modified for use with Native Client.
#if (defined(__ARM_NEON__) || \
@@ -679,4 +675,4 @@ void VP8FiltersInit(void);
} // extern "C"
#endif
-#endif /* WEBP_DSP_DSP_H_ */
+#endif // WEBP_DSP_DSP_H_
diff --git a/thirdparty/libwebp/src/dsp/enc.c b/thirdparty/libwebp/src/dsp/enc.c
index fa23b40a30..2fddbc4c52 100644
--- a/thirdparty/libwebp/src/dsp/enc.c
+++ b/thirdparty/libwebp/src/dsp/enc.c
@@ -734,7 +734,6 @@ VP8BlockCopy VP8Copy16x8;
extern void VP8EncDspInitSSE2(void);
extern void VP8EncDspInitSSE41(void);
-extern void VP8EncDspInitAVX2(void);
extern void VP8EncDspInitNEON(void);
extern void VP8EncDspInitMIPS32(void);
extern void VP8EncDspInitMIPSdspR2(void);
@@ -784,11 +783,6 @@ WEBP_DSP_INIT_FUNC(VP8EncDspInit) {
#endif
}
#endif
-#if defined(WEBP_USE_AVX2)
- if (VP8GetCPUInfo(kAVX2)) {
- VP8EncDspInitAVX2();
- }
-#endif
#if defined(WEBP_USE_MIPS32)
if (VP8GetCPUInfo(kMIPS32)) {
VP8EncDspInitMIPS32();
diff --git a/thirdparty/libwebp/src/dsp/enc_avx2.c b/thirdparty/libwebp/src/dsp/enc_avx2.c
deleted file mode 100644
index 8bc5798fee..0000000000
--- a/thirdparty/libwebp/src/dsp/enc_avx2.c
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// AVX2 version of speed-critical encoding functions.
-
-#include "src/dsp/dsp.h"
-
-#if defined(WEBP_USE_AVX2)
-
-#endif // WEBP_USE_AVX2
-
-//------------------------------------------------------------------------------
-// Entry point
-
-WEBP_DSP_INIT_STUB(VP8EncDspInitAVX2)
diff --git a/thirdparty/libwebp/src/dsp/lossless.c b/thirdparty/libwebp/src/dsp/lossless.c
index f9b3c182d3..d21aa6a0a0 100644
--- a/thirdparty/libwebp/src/dsp/lossless.c
+++ b/thirdparty/libwebp/src/dsp/lossless.c
@@ -23,8 +23,6 @@
#include "src/dsp/lossless.h"
#include "src/dsp/lossless_common.h"
-#define MAX_DIFF_COST (1e30f)
-
//------------------------------------------------------------------------------
// Image transforms.
diff --git a/thirdparty/libwebp/src/dsp/lossless.h b/thirdparty/libwebp/src/dsp/lossless.h
index b2bbdfc93c..f709cc86b2 100644
--- a/thirdparty/libwebp/src/dsp/lossless.h
+++ b/thirdparty/libwebp/src/dsp/lossless.h
@@ -163,7 +163,7 @@ extern VP8LCostCombinedFunc VP8LExtraCostCombined;
extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy;
typedef struct { // small struct to hold counters
- int counts[2]; // index: 0=zero steak, 1=non-zero streak
+ int counts[2]; // index: 0=zero streak, 1=non-zero streak
int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3]
} VP8LStreaks;
@@ -194,10 +194,14 @@ extern VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined;
void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n,
VP8LBitEntropy* const entropy);
-typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out);
-extern VP8LHistogramAddFunc VP8LHistogramAdd;
+typedef void (*VP8LAddVectorFunc)(const uint32_t* a, const uint32_t* b,
+ uint32_t* out, int size);
+extern VP8LAddVectorFunc VP8LAddVector;
+typedef void (*VP8LAddVectorEqFunc)(const uint32_t* a, uint32_t* out, int size);
+extern VP8LAddVectorEqFunc VP8LAddVectorEq;
+void VP8LHistogramAdd(const VP8LHistogram* const a,
+ const VP8LHistogram* const b,
+ VP8LHistogram* const out);
// -----------------------------------------------------------------------------
// PrefixEncode()
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc.c b/thirdparty/libwebp/src/dsp/lossless_enc.c
index d608326fef..1408fbf580 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc.c
@@ -632,38 +632,67 @@ static double ExtraCostCombined_C(const uint32_t* X, const uint32_t* Y,
//------------------------------------------------------------------------------
-static void HistogramAdd_C(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out) {
+static void AddVector_C(const uint32_t* a, const uint32_t* b, uint32_t* out,
+ int size) {
+ int i;
+ for (i = 0; i < size; ++i) out[i] = a[i] + b[i];
+}
+
+static void AddVectorEq_C(const uint32_t* a, uint32_t* out, int size) {
+ int i;
+ for (i = 0; i < size; ++i) out[i] += a[i];
+}
+
+#define ADD(X, ARG, LEN) do { \
+ if (a->is_used_[X]) { \
+ if (b->is_used_[X]) { \
+ VP8LAddVector(a->ARG, b->ARG, out->ARG, (LEN)); \
+ } else { \
+ memcpy(&out->ARG[0], &a->ARG[0], (LEN) * sizeof(out->ARG[0])); \
+ } \
+ } else if (b->is_used_[X]) { \
+ memcpy(&out->ARG[0], &b->ARG[0], (LEN) * sizeof(out->ARG[0])); \
+ } else { \
+ memset(&out->ARG[0], 0, (LEN) * sizeof(out->ARG[0])); \
+ } \
+} while (0)
+
+#define ADD_EQ(X, ARG, LEN) do { \
+ if (a->is_used_[X]) { \
+ if (out->is_used_[X]) { \
+ VP8LAddVectorEq(a->ARG, out->ARG, (LEN)); \
+ } else { \
+ memcpy(&out->ARG[0], &a->ARG[0], (LEN) * sizeof(out->ARG[0])); \
+ } \
+ } \
+} while (0)
+
+void VP8LHistogramAdd(const VP8LHistogram* const a,
+ const VP8LHistogram* const b, VP8LHistogram* const out) {
int i;
const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
assert(a->palette_code_bits_ == b->palette_code_bits_);
+
if (b != out) {
- for (i = 0; i < literal_size; ++i) {
- out->literal_[i] = a->literal_[i] + b->literal_[i];
- }
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- out->distance_[i] = a->distance_[i] + b->distance_[i];
- }
- for (i = 0; i < NUM_LITERAL_CODES; ++i) {
- out->red_[i] = a->red_[i] + b->red_[i];
- out->blue_[i] = a->blue_[i] + b->blue_[i];
- out->alpha_[i] = a->alpha_[i] + b->alpha_[i];
+ ADD(0, literal_, literal_size);
+ ADD(1, red_, NUM_LITERAL_CODES);
+ ADD(2, blue_, NUM_LITERAL_CODES);
+ ADD(3, alpha_, NUM_LITERAL_CODES);
+ ADD(4, distance_, NUM_DISTANCE_CODES);
+ for (i = 0; i < 5; ++i) {
+ out->is_used_[i] = (a->is_used_[i] | b->is_used_[i]);
}
} else {
- for (i = 0; i < literal_size; ++i) {
- out->literal_[i] += a->literal_[i];
- }
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- out->distance_[i] += a->distance_[i];
- }
- for (i = 0; i < NUM_LITERAL_CODES; ++i) {
- out->red_[i] += a->red_[i];
- out->blue_[i] += a->blue_[i];
- out->alpha_[i] += a->alpha_[i];
- }
+ ADD_EQ(0, literal_, literal_size);
+ ADD_EQ(1, red_, NUM_LITERAL_CODES);
+ ADD_EQ(2, blue_, NUM_LITERAL_CODES);
+ ADD_EQ(3, alpha_, NUM_LITERAL_CODES);
+ ADD_EQ(4, distance_, NUM_DISTANCE_CODES);
+ for (i = 0; i < 5; ++i) out->is_used_[i] |= a->is_used_[i];
}
}
+#undef ADD
+#undef ADD_EQ
//------------------------------------------------------------------------------
// Image transforms.
@@ -848,7 +877,8 @@ VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy;
VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined;
VP8LGetCombinedEntropyUnrefinedFunc VP8LGetCombinedEntropyUnrefined;
-VP8LHistogramAddFunc VP8LHistogramAdd;
+VP8LAddVectorFunc VP8LAddVector;
+VP8LAddVectorEqFunc VP8LAddVectorEq;
VP8LVectorMismatchFunc VP8LVectorMismatch;
VP8LBundleColorMapFunc VP8LBundleColorMap;
@@ -885,7 +915,8 @@ WEBP_DSP_INIT_FUNC(VP8LEncDspInit) {
VP8LGetEntropyUnrefined = GetEntropyUnrefined_C;
VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_C;
- VP8LHistogramAdd = HistogramAdd_C;
+ VP8LAddVector = AddVector_C;
+ VP8LAddVectorEq = AddVectorEq_C;
VP8LVectorMismatch = VectorMismatch_C;
VP8LBundleColorMap = VP8LBundleColorMap_C;
@@ -971,7 +1002,8 @@ WEBP_DSP_INIT_FUNC(VP8LEncDspInit) {
assert(VP8LCombinedShannonEntropy != NULL);
assert(VP8LGetEntropyUnrefined != NULL);
assert(VP8LGetCombinedEntropyUnrefined != NULL);
- assert(VP8LHistogramAdd != NULL);
+ assert(VP8LAddVector != NULL);
+ assert(VP8LAddVectorEq != NULL);
assert(VP8LVectorMismatch != NULL);
assert(VP8LBundleColorMap != NULL);
assert(VP8LPredictorsSub[0] != NULL);
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc_mips32.c b/thirdparty/libwebp/src/dsp/lossless_enc_mips32.c
index e7b58f4e8c..0412a093cf 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc_mips32.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc_mips32.c
@@ -344,65 +344,29 @@ static void GetCombinedEntropyUnrefined_MIPS32(const uint32_t X[],
ASM_END_COMMON_0 \
ASM_END_COMMON_1
-#define ADD_VECTOR(A, B, OUT, SIZE, EXTRA_SIZE) do { \
- const uint32_t* pa = (const uint32_t*)(A); \
- const uint32_t* pb = (const uint32_t*)(B); \
- uint32_t* pout = (uint32_t*)(OUT); \
- const uint32_t* const LoopEnd = pa + (SIZE); \
- assert((SIZE) % 4 == 0); \
- ASM_START \
- ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout) \
- ASM_END_0 \
- if ((EXTRA_SIZE) > 0) { \
- const int last = (EXTRA_SIZE); \
- int i; \
- for (i = 0; i < last; ++i) pout[i] = pa[i] + pb[i]; \
- } \
-} while (0)
-
-#define ADD_VECTOR_EQ(A, OUT, SIZE, EXTRA_SIZE) do { \
- const uint32_t* pa = (const uint32_t*)(A); \
- uint32_t* pout = (uint32_t*)(OUT); \
- const uint32_t* const LoopEnd = pa + (SIZE); \
- assert((SIZE) % 4 == 0); \
- ASM_START \
- ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout) \
- ASM_END_1 \
- if ((EXTRA_SIZE) > 0) { \
- const int last = (EXTRA_SIZE); \
- int i; \
- for (i = 0; i < last; ++i) pout[i] += pa[i]; \
- } \
-} while (0)
-
-static void HistogramAdd_MIPS32(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out) {
+static void AddVector_MIPS32(const uint32_t* pa, const uint32_t* pb,
+ uint32_t* pout, int size) {
uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
- const int extra_cache_size = VP8LHistogramNumCodes(a->palette_code_bits_)
- - (NUM_LITERAL_CODES + NUM_LENGTH_CODES);
- assert(a->palette_code_bits_ == b->palette_code_bits_);
-
- if (b != out) {
- ADD_VECTOR(a->literal_, b->literal_, out->literal_,
- NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
- ADD_VECTOR(a->distance_, b->distance_, out->distance_,
- NUM_DISTANCE_CODES, 0);
- ADD_VECTOR(a->red_, b->red_, out->red_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
- } else {
- ADD_VECTOR_EQ(a->literal_, out->literal_,
- NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
- ADD_VECTOR_EQ(a->distance_, out->distance_, NUM_DISTANCE_CODES, 0);
- ADD_VECTOR_EQ(a->red_, out->red_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR_EQ(a->blue_, out->blue_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR_EQ(a->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
- }
+ const uint32_t end = ((size) / 4) * 4;
+ const uint32_t* const LoopEnd = pa + end;
+ int i;
+ ASM_START
+ ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout)
+ ASM_END_0
+ for (i = end; i < size; ++i) pout[i] = pa[i] + pb[i];
+}
+
+static void AddVectorEq_MIPS32(const uint32_t* pa, uint32_t* pout, int size) {
+ uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
+ const uint32_t end = ((size) / 4) * 4;
+ const uint32_t* const LoopEnd = pa + end;
+ int i;
+ ASM_START
+ ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout)
+ ASM_END_1
+ for (i = end; i < size; ++i) pout[i] += pa[i];
}
-#undef ADD_VECTOR_EQ
-#undef ADD_VECTOR
#undef ASM_END_1
#undef ASM_END_0
#undef ASM_END_COMMON_1
@@ -422,7 +386,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) {
VP8LExtraCostCombined = ExtraCostCombined_MIPS32;
VP8LGetEntropyUnrefined = GetEntropyUnrefined_MIPS32;
VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_MIPS32;
- VP8LHistogramAdd = HistogramAdd_MIPS32;
+ VP8LAddVector = AddVector_MIPS32;
+ VP8LAddVectorEq = AddVectorEq_MIPS32;
}
#else // !WEBP_USE_MIPS32
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
index f84a9909e1..36478c4912 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
@@ -170,12 +170,13 @@ static void CollectColorRedTransforms_SSE2(const uint32_t* argb, int stride,
//------------------------------------------------------------------------------
+// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But
+// that's ok since the histogram values are less than 1<<28 (max picture size).
#define LINE_SIZE 16 // 8 or 16
static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out,
int size) {
int i;
- assert(size % LINE_SIZE == 0);
- for (i = 0; i < size; i += LINE_SIZE) {
+ for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) {
const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
#if (LINE_SIZE == 16)
@@ -195,12 +196,14 @@ static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out,
_mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
#endif
}
+ for (; i < size; ++i) {
+ out[i] = a[i] + b[i];
+ }
}
static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) {
int i;
- assert(size % LINE_SIZE == 0);
- for (i = 0; i < size; i += LINE_SIZE) {
+ for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) {
const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
#if (LINE_SIZE == 16)
@@ -220,35 +223,11 @@ static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) {
_mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
#endif
}
-}
-#undef LINE_SIZE
-
-// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But
-// that's ok since the histogram values are less than 1<<28 (max picture size).
-static void HistogramAdd_SSE2(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out) {
- int i;
- const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
- assert(a->palette_code_bits_ == b->palette_code_bits_);
- if (b != out) {
- AddVector_SSE2(a->literal_, b->literal_, out->literal_, NUM_LITERAL_CODES);
- AddVector_SSE2(a->red_, b->red_, out->red_, NUM_LITERAL_CODES);
- AddVector_SSE2(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES);
- AddVector_SSE2(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES);
- } else {
- AddVectorEq_SSE2(a->literal_, out->literal_, NUM_LITERAL_CODES);
- AddVectorEq_SSE2(a->red_, out->red_, NUM_LITERAL_CODES);
- AddVectorEq_SSE2(a->blue_, out->blue_, NUM_LITERAL_CODES);
- AddVectorEq_SSE2(a->alpha_, out->alpha_, NUM_LITERAL_CODES);
- }
- for (i = NUM_LITERAL_CODES; i < literal_size; ++i) {
- out->literal_[i] = a->literal_[i] + b->literal_[i];
- }
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- out->distance_[i] = a->distance_[i] + b->distance_[i];
+ for (; i < size; ++i) {
+ out[i] += a[i];
}
}
+#undef LINE_SIZE
//------------------------------------------------------------------------------
// Entropy
@@ -675,7 +654,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) {
VP8LTransformColor = TransformColor_SSE2;
VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE2;
VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE2;
- VP8LHistogramAdd = HistogramAdd_SSE2;
+ VP8LAddVector = AddVector_SSE2;
+ VP8LAddVectorEq = AddVectorEq_SSE2;
VP8LCombinedShannonEntropy = CombinedShannonEntropy_SSE2;
VP8LVectorMismatch = VectorMismatch_SSE2;
VP8LBundleColorMap = BundleColorMap_SSE2;
diff --git a/thirdparty/libwebp/src/dsp/msa_macro.h b/thirdparty/libwebp/src/dsp/msa_macro.h
index dfacda6ccd..de026a1d9e 100644
--- a/thirdparty/libwebp/src/dsp/msa_macro.h
+++ b/thirdparty/libwebp/src/dsp/msa_macro.h
@@ -1389,4 +1389,4 @@ static WEBP_INLINE uint32_t func_hadd_uh_u32(v8u16 in) {
} while (0)
#define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__)
-#endif /* WEBP_DSP_MSA_MACRO_H_ */
+#endif // WEBP_DSP_MSA_MACRO_H_
diff --git a/thirdparty/libwebp/src/dsp/rescaler.c b/thirdparty/libwebp/src/dsp/rescaler.c
index f307d35056..753f84fcf4 100644
--- a/thirdparty/libwebp/src/dsp/rescaler.c
+++ b/thirdparty/libwebp/src/dsp/rescaler.c
@@ -21,6 +21,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
//------------------------------------------------------------------------------
// Row import
@@ -138,7 +139,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
if (yscale) {
for (x_out = 0; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -153,6 +154,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
}
}
+#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER
diff --git a/thirdparty/libwebp/src/dsp/rescaler_mips32.c b/thirdparty/libwebp/src/dsp/rescaler_mips32.c
index 542f7e5970..61f63c616c 100644
--- a/thirdparty/libwebp/src/dsp/rescaler_mips32.c
+++ b/thirdparty/libwebp/src/dsp/rescaler_mips32.c
@@ -209,6 +209,7 @@ static void ExportRowExpand_MIPS32(WebPRescaler* const wrk) {
}
}
+#if 0 // disabled for now. TODO(skal): make match the C-code
static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) {
const int x_out_max = wrk->dst_width * wrk->num_channels;
uint8_t* dst = wrk->dst;
@@ -273,6 +274,7 @@ static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) {
);
}
}
+#endif // 0
//------------------------------------------------------------------------------
// Entry point
@@ -283,7 +285,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) {
WebPRescalerImportRowExpand = ImportRowExpand_MIPS32;
WebPRescalerImportRowShrink = ImportRowShrink_MIPS32;
WebPRescalerExportRowExpand = ExportRowExpand_MIPS32;
- WebPRescalerExportRowShrink = ExportRowShrink_MIPS32;
+// WebPRescalerExportRowShrink = ExportRowShrink_MIPS32;
}
#else // !WEBP_USE_MIPS32
diff --git a/thirdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c b/thirdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c
index b78aac15e6..ce9e64862e 100644
--- a/thirdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c
+++ b/thirdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c
@@ -20,10 +20,12 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
//------------------------------------------------------------------------------
// Row export
+#if 0 // disabled for now. TODO(skal): make match the C-code
static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
int i;
const int x_out_max = wrk->dst_width * wrk->num_channels;
@@ -106,7 +108,7 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
}
for (i = 0; i < (x_out_max & 0x3); ++i) {
const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale);
- const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(*irow - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
*dst++ = v;
*irow++ = frac; // new fractional start
@@ -154,13 +156,14 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
);
}
for (i = 0; i < (x_out_max & 0x3); ++i) {
- const int v = (int)MULT_FIX(*irow, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(*irow, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
*dst++ = v;
*irow++ = 0;
}
}
}
+#endif // 0
static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
int i;
@@ -294,6 +297,7 @@ static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
}
}
+#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER
@@ -304,7 +308,7 @@ extern void WebPRescalerDspInitMIPSdspR2(void);
WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) {
WebPRescalerExportRowExpand = ExportRowExpand_MIPSdspR2;
- WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2;
+// WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2;
}
#else // !WEBP_USE_MIPS_DSP_R2
diff --git a/thirdparty/libwebp/src/dsp/rescaler_msa.c b/thirdparty/libwebp/src/dsp/rescaler_msa.c
index f3bc99f1cd..c559254836 100644
--- a/thirdparty/libwebp/src/dsp/rescaler_msa.c
+++ b/thirdparty/libwebp/src/dsp/rescaler_msa.c
@@ -22,6 +22,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
#define CALC_MULT_FIX_16(in0, in1, in2, in3, scale, shift, dst) do { \
v4u32 tmp0, tmp1, tmp2, tmp3; \
@@ -262,6 +263,7 @@ static void RescalerExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
}
}
+#if 0 // disabled for now. TODO(skal): make match the C-code
static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
uint8_t* dst, int length,
const uint32_t yscale,
@@ -341,7 +343,7 @@ static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
}
for (x_out = 0; x_out < length; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac;
@@ -426,6 +428,7 @@ static void RescalerExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
ExportRowShrink_1(irow, dst, x_out_max, wrk);
}
}
+#endif // 0
//------------------------------------------------------------------------------
// Entry point
@@ -434,7 +437,7 @@ extern void WebPRescalerDspInitMSA(void);
WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMSA(void) {
WebPRescalerExportRowExpand = RescalerExportRowExpand_MIPSdspR2;
- WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2;
+// WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2;
}
#else // !WEBP_USE_MSA
diff --git a/thirdparty/libwebp/src/dsp/rescaler_neon.c b/thirdparty/libwebp/src/dsp/rescaler_neon.c
index 3eff9fbaf4..a553f06f79 100644
--- a/thirdparty/libwebp/src/dsp/rescaler_neon.c
+++ b/thirdparty/libwebp/src/dsp/rescaler_neon.c
@@ -22,6 +22,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR_C(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC))
#define LOAD_32x8(SRC, DST0, DST1) \
@@ -35,8 +36,11 @@
#if (WEBP_RESCALER_RFIX == 32)
#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1))
-#define MULT_FIX(A, B) /* note: B is actualy scale>>1. See MAKE_HALF_CST */ \
+// note: B is actualy scale>>1. See MAKE_HALF_CST
+#define MULT_FIX(A, B) \
vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
+#define MULT_FIX_FLOOR(A, B) \
+ vreinterpretq_u32_s32(vqdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
#else
#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work"
#endif
@@ -135,8 +139,8 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
const uint32x4_t A1 = MULT_FIX(in1, yscale_half);
const uint32x4_t B0 = vqsubq_u32(in2, A0);
const uint32x4_t B1 = vqsubq_u32(in3, A1);
- const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half);
- const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half);
+ const uint32x4_t C0 = MULT_FIX_FLOOR(B0, fxy_scale_half);
+ const uint32x4_t C1 = MULT_FIX_FLOOR(B1, fxy_scale_half);
const uint16x4_t D0 = vmovn_u32(C0);
const uint16x4_t D1 = vmovn_u32(C1);
const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1));
@@ -145,7 +149,7 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
}
for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale);
- const int v = (int)MULT_FIX_C(irow[x_out] - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR_C(irow[x_out] - frac, fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -170,6 +174,12 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
}
}
+#undef MULT_FIX_FLOOR_C
+#undef MULT_FIX_C
+#undef MULT_FIX_FLOOR
+#undef MULT_FIX
+#undef ROUNDER
+
//------------------------------------------------------------------------------
extern void WebPRescalerDspInitNEON(void);
diff --git a/thirdparty/libwebp/src/dsp/rescaler_sse2.c b/thirdparty/libwebp/src/dsp/rescaler_sse2.c
index 64c50deab5..f7461a452c 100644
--- a/thirdparty/libwebp/src/dsp/rescaler_sse2.c
+++ b/thirdparty/libwebp/src/dsp/rescaler_sse2.c
@@ -25,6 +25,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0
static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) {
@@ -224,6 +225,35 @@ static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0,
_mm_storel_epi64((__m128i*)dst, G);
}
+static WEBP_INLINE void ProcessRow_Floor_SSE2(const __m128i* const A0,
+ const __m128i* const A1,
+ const __m128i* const A2,
+ const __m128i* const A3,
+ const __m128i* const mult,
+ uint8_t* const dst) {
+ const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0);
+ const __m128i B0 = _mm_mul_epu32(*A0, *mult);
+ const __m128i B1 = _mm_mul_epu32(*A1, *mult);
+ const __m128i B2 = _mm_mul_epu32(*A2, *mult);
+ const __m128i B3 = _mm_mul_epu32(*A3, *mult);
+ const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX);
+ const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX);
+#if (WEBP_RESCALER_RFIX < 32)
+ const __m128i D2 =
+ _mm_and_si128(_mm_slli_epi64(B2, 32 - WEBP_RESCALER_RFIX), mask);
+ const __m128i D3 =
+ _mm_and_si128(_mm_slli_epi64(B3, 32 - WEBP_RESCALER_RFIX), mask);
+#else
+ const __m128i D2 = _mm_and_si128(B2, mask);
+ const __m128i D3 = _mm_and_si128(B3, mask);
+#endif
+ const __m128i E0 = _mm_or_si128(D0, D2);
+ const __m128i E1 = _mm_or_si128(D1, D3);
+ const __m128i F = _mm_packs_epi32(E0, E1);
+ const __m128i G = _mm_packus_epi16(F, F);
+ _mm_storel_epi64((__m128i*)dst, G);
+}
+
static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
int x_out;
uint8_t* const dst = wrk->dst;
@@ -322,12 +352,12 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
const __m128i G1 = _mm_or_si128(D1, F3);
_mm_storeu_si128((__m128i*)(irow + x_out + 0), G0);
_mm_storeu_si128((__m128i*)(irow + x_out + 4), G1);
- ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
+ ProcessRow_Floor_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
}
}
for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale);
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -352,6 +382,7 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
}
}
+#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER
diff --git a/thirdparty/libwebp/src/dsp/yuv.h b/thirdparty/libwebp/src/dsp/yuv.h
index eb787270d2..c12be1d094 100644
--- a/thirdparty/libwebp/src/dsp/yuv.h
+++ b/thirdparty/libwebp/src/dsp/yuv.h
@@ -207,4 +207,4 @@ static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) {
} // extern "C"
#endif
-#endif /* WEBP_DSP_YUV_H_ */
+#endif // WEBP_DSP_YUV_H_
diff --git a/thirdparty/libwebp/src/enc/analysis_enc.c b/thirdparty/libwebp/src/enc/analysis_enc.c
index a47ff7d4e8..687757ae03 100644
--- a/thirdparty/libwebp/src/enc/analysis_enc.c
+++ b/thirdparty/libwebp/src/enc/analysis_enc.c
@@ -458,7 +458,7 @@ static void MergeJobs(const SegmentJob* const src, SegmentJob* const dst) {
dst->uv_alpha += src->uv_alpha;
}
-// initialize the job struct with some TODOs
+// initialize the job struct with some tasks to perform
static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job,
int start_row, int end_row) {
WebPGetWorkerInterface()->Init(&job->worker);
diff --git a/thirdparty/libwebp/src/enc/backward_references_cost_enc.c b/thirdparty/libwebp/src/enc/backward_references_cost_enc.c
index 7175496c7f..516abd73eb 100644
--- a/thirdparty/libwebp/src/enc/backward_references_cost_enc.c
+++ b/thirdparty/libwebp/src/enc/backward_references_cost_enc.c
@@ -67,7 +67,7 @@ static int CostModelBuild(CostModel* const m, int xsize, int cache_bits,
// The following code is similar to VP8LHistogramCreate but converts the
// distance to plane code.
- VP8LHistogramInit(histo, cache_bits);
+ VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 1);
while (VP8LRefsCursorOk(&c)) {
VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos, VP8LDistanceToPlaneCode,
xsize);
diff --git a/thirdparty/libwebp/src/enc/backward_references_enc.c b/thirdparty/libwebp/src/enc/backward_references_enc.c
index 39230188b9..3ab7b0ac7d 100644
--- a/thirdparty/libwebp/src/enc/backward_references_enc.c
+++ b/thirdparty/libwebp/src/enc/backward_references_enc.c
@@ -715,6 +715,7 @@ static int CalculateBestCacheSize(const uint32_t* argb, int quality,
for (i = 0; i <= cache_bits_max; ++i) {
histos[i] = VP8LAllocateHistogram(i);
if (histos[i] == NULL) goto Error;
+ VP8LHistogramInit(histos[i], i, /*init_arrays=*/ 1);
if (i == 0) continue;
cc_init[i] = VP8LColorCacheInit(&hashers[i], i);
if (!cc_init[i]) goto Error;
diff --git a/thirdparty/libwebp/src/enc/cost_enc.h b/thirdparty/libwebp/src/enc/cost_enc.h
index bdce1e6a3b..a4b177b342 100644
--- a/thirdparty/libwebp/src/enc/cost_enc.h
+++ b/thirdparty/libwebp/src/enc/cost_enc.h
@@ -79,4 +79,4 @@ extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES];
} // extern "C"
#endif
-#endif /* WEBP_ENC_COST_ENC_H_ */
+#endif // WEBP_ENC_COST_ENC_H_
diff --git a/thirdparty/libwebp/src/enc/delta_palettization_enc.c b/thirdparty/libwebp/src/enc/delta_palettization_enc.c
deleted file mode 100644
index a61c8e6c93..0000000000
--- a/thirdparty/libwebp/src/enc/delta_palettization_enc.c
+++ /dev/null
@@ -1,455 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Mislav Bradac (mislavm@google.com)
-//
-
-#include "src/enc/delta_palettization_enc.h"
-
-#ifdef WEBP_EXPERIMENTAL_FEATURES
-#include "src/webp/types.h"
-#include "src/dsp/lossless.h"
-
-#define MK_COL(r, g, b) (((r) << 16) + ((g) << 8) + (b))
-
-// Format allows palette up to 256 entries, but more palette entries produce
-// bigger entropy. In the future it will probably be useful to add more entries
-// that are far from the origin of the palette or choose remaining entries
-// dynamically.
-#define DELTA_PALETTE_SIZE 226
-
-// Palette used for delta_palettization. Entries are roughly sorted by distance
-// of their signed equivalents from the origin.
-static const uint32_t kDeltaPalette[DELTA_PALETTE_SIZE] = {
- MK_COL(0u, 0u, 0u),
- MK_COL(255u, 255u, 255u),
- MK_COL(1u, 1u, 1u),
- MK_COL(254u, 254u, 254u),
- MK_COL(2u, 2u, 2u),
- MK_COL(4u, 4u, 4u),
- MK_COL(252u, 252u, 252u),
- MK_COL(250u, 0u, 0u),
- MK_COL(0u, 250u, 0u),
- MK_COL(0u, 0u, 250u),
- MK_COL(6u, 0u, 0u),
- MK_COL(0u, 6u, 0u),
- MK_COL(0u, 0u, 6u),
- MK_COL(0u, 0u, 248u),
- MK_COL(0u, 0u, 8u),
- MK_COL(0u, 248u, 0u),
- MK_COL(0u, 248u, 248u),
- MK_COL(0u, 248u, 8u),
- MK_COL(0u, 8u, 0u),
- MK_COL(0u, 8u, 248u),
- MK_COL(0u, 8u, 8u),
- MK_COL(8u, 8u, 8u),
- MK_COL(248u, 0u, 0u),
- MK_COL(248u, 0u, 248u),
- MK_COL(248u, 0u, 8u),
- MK_COL(248u, 248u, 0u),
- MK_COL(248u, 8u, 0u),
- MK_COL(8u, 0u, 0u),
- MK_COL(8u, 0u, 248u),
- MK_COL(8u, 0u, 8u),
- MK_COL(8u, 248u, 0u),
- MK_COL(8u, 8u, 0u),
- MK_COL(23u, 23u, 23u),
- MK_COL(13u, 13u, 13u),
- MK_COL(232u, 232u, 232u),
- MK_COL(244u, 244u, 244u),
- MK_COL(245u, 245u, 250u),
- MK_COL(50u, 50u, 50u),
- MK_COL(204u, 204u, 204u),
- MK_COL(236u, 236u, 236u),
- MK_COL(16u, 16u, 16u),
- MK_COL(240u, 16u, 16u),
- MK_COL(16u, 240u, 16u),
- MK_COL(240u, 240u, 16u),
- MK_COL(16u, 16u, 240u),
- MK_COL(240u, 16u, 240u),
- MK_COL(16u, 240u, 240u),
- MK_COL(240u, 240u, 240u),
- MK_COL(0u, 0u, 232u),
- MK_COL(0u, 232u, 0u),
- MK_COL(232u, 0u, 0u),
- MK_COL(0u, 0u, 24u),
- MK_COL(0u, 24u, 0u),
- MK_COL(24u, 0u, 0u),
- MK_COL(32u, 32u, 32u),
- MK_COL(224u, 32u, 32u),
- MK_COL(32u, 224u, 32u),
- MK_COL(224u, 224u, 32u),
- MK_COL(32u, 32u, 224u),
- MK_COL(224u, 32u, 224u),
- MK_COL(32u, 224u, 224u),
- MK_COL(224u, 224u, 224u),
- MK_COL(0u, 0u, 176u),
- MK_COL(0u, 0u, 80u),
- MK_COL(0u, 176u, 0u),
- MK_COL(0u, 176u, 176u),
- MK_COL(0u, 176u, 80u),
- MK_COL(0u, 80u, 0u),
- MK_COL(0u, 80u, 176u),
- MK_COL(0u, 80u, 80u),
- MK_COL(176u, 0u, 0u),
- MK_COL(176u, 0u, 176u),
- MK_COL(176u, 0u, 80u),
- MK_COL(176u, 176u, 0u),
- MK_COL(176u, 80u, 0u),
- MK_COL(80u, 0u, 0u),
- MK_COL(80u, 0u, 176u),
- MK_COL(80u, 0u, 80u),
- MK_COL(80u, 176u, 0u),
- MK_COL(80u, 80u, 0u),
- MK_COL(0u, 0u, 152u),
- MK_COL(0u, 0u, 104u),
- MK_COL(0u, 152u, 0u),
- MK_COL(0u, 152u, 152u),
- MK_COL(0u, 152u, 104u),
- MK_COL(0u, 104u, 0u),
- MK_COL(0u, 104u, 152u),
- MK_COL(0u, 104u, 104u),
- MK_COL(152u, 0u, 0u),
- MK_COL(152u, 0u, 152u),
- MK_COL(152u, 0u, 104u),
- MK_COL(152u, 152u, 0u),
- MK_COL(152u, 104u, 0u),
- MK_COL(104u, 0u, 0u),
- MK_COL(104u, 0u, 152u),
- MK_COL(104u, 0u, 104u),
- MK_COL(104u, 152u, 0u),
- MK_COL(104u, 104u, 0u),
- MK_COL(216u, 216u, 216u),
- MK_COL(216u, 216u, 40u),
- MK_COL(216u, 216u, 176u),
- MK_COL(216u, 216u, 80u),
- MK_COL(216u, 40u, 216u),
- MK_COL(216u, 40u, 40u),
- MK_COL(216u, 40u, 176u),
- MK_COL(216u, 40u, 80u),
- MK_COL(216u, 176u, 216u),
- MK_COL(216u, 176u, 40u),
- MK_COL(216u, 176u, 176u),
- MK_COL(216u, 176u, 80u),
- MK_COL(216u, 80u, 216u),
- MK_COL(216u, 80u, 40u),
- MK_COL(216u, 80u, 176u),
- MK_COL(216u, 80u, 80u),
- MK_COL(40u, 216u, 216u),
- MK_COL(40u, 216u, 40u),
- MK_COL(40u, 216u, 176u),
- MK_COL(40u, 216u, 80u),
- MK_COL(40u, 40u, 216u),
- MK_COL(40u, 40u, 40u),
- MK_COL(40u, 40u, 176u),
- MK_COL(40u, 40u, 80u),
- MK_COL(40u, 176u, 216u),
- MK_COL(40u, 176u, 40u),
- MK_COL(40u, 176u, 176u),
- MK_COL(40u, 176u, 80u),
- MK_COL(40u, 80u, 216u),
- MK_COL(40u, 80u, 40u),
- MK_COL(40u, 80u, 176u),
- MK_COL(40u, 80u, 80u),
- MK_COL(80u, 216u, 216u),
- MK_COL(80u, 216u, 40u),
- MK_COL(80u, 216u, 176u),
- MK_COL(80u, 216u, 80u),
- MK_COL(80u, 40u, 216u),
- MK_COL(80u, 40u, 40u),
- MK_COL(80u, 40u, 176u),
- MK_COL(80u, 40u, 80u),
- MK_COL(80u, 176u, 216u),
- MK_COL(80u, 176u, 40u),
- MK_COL(80u, 176u, 176u),
- MK_COL(80u, 176u, 80u),
- MK_COL(80u, 80u, 216u),
- MK_COL(80u, 80u, 40u),
- MK_COL(80u, 80u, 176u),
- MK_COL(80u, 80u, 80u),
- MK_COL(0u, 0u, 192u),
- MK_COL(0u, 0u, 64u),
- MK_COL(0u, 0u, 128u),
- MK_COL(0u, 192u, 0u),
- MK_COL(0u, 192u, 192u),
- MK_COL(0u, 192u, 64u),
- MK_COL(0u, 192u, 128u),
- MK_COL(0u, 64u, 0u),
- MK_COL(0u, 64u, 192u),
- MK_COL(0u, 64u, 64u),
- MK_COL(0u, 64u, 128u),
- MK_COL(0u, 128u, 0u),
- MK_COL(0u, 128u, 192u),
- MK_COL(0u, 128u, 64u),
- MK_COL(0u, 128u, 128u),
- MK_COL(176u, 216u, 216u),
- MK_COL(176u, 216u, 40u),
- MK_COL(176u, 216u, 176u),
- MK_COL(176u, 216u, 80u),
- MK_COL(176u, 40u, 216u),
- MK_COL(176u, 40u, 40u),
- MK_COL(176u, 40u, 176u),
- MK_COL(176u, 40u, 80u),
- MK_COL(176u, 176u, 216u),
- MK_COL(176u, 176u, 40u),
- MK_COL(176u, 176u, 176u),
- MK_COL(176u, 176u, 80u),
- MK_COL(176u, 80u, 216u),
- MK_COL(176u, 80u, 40u),
- MK_COL(176u, 80u, 176u),
- MK_COL(176u, 80u, 80u),
- MK_COL(192u, 0u, 0u),
- MK_COL(192u, 0u, 192u),
- MK_COL(192u, 0u, 64u),
- MK_COL(192u, 0u, 128u),
- MK_COL(192u, 192u, 0u),
- MK_COL(192u, 192u, 192u),
- MK_COL(192u, 192u, 64u),
- MK_COL(192u, 192u, 128u),
- MK_COL(192u, 64u, 0u),
- MK_COL(192u, 64u, 192u),
- MK_COL(192u, 64u, 64u),
- MK_COL(192u, 64u, 128u),
- MK_COL(192u, 128u, 0u),
- MK_COL(192u, 128u, 192u),
- MK_COL(192u, 128u, 64u),
- MK_COL(192u, 128u, 128u),
- MK_COL(64u, 0u, 0u),
- MK_COL(64u, 0u, 192u),
- MK_COL(64u, 0u, 64u),
- MK_COL(64u, 0u, 128u),
- MK_COL(64u, 192u, 0u),
- MK_COL(64u, 192u, 192u),
- MK_COL(64u, 192u, 64u),
- MK_COL(64u, 192u, 128u),
- MK_COL(64u, 64u, 0u),
- MK_COL(64u, 64u, 192u),
- MK_COL(64u, 64u, 64u),
- MK_COL(64u, 64u, 128u),
- MK_COL(64u, 128u, 0u),
- MK_COL(64u, 128u, 192u),
- MK_COL(64u, 128u, 64u),
- MK_COL(64u, 128u, 128u),
- MK_COL(128u, 0u, 0u),
- MK_COL(128u, 0u, 192u),
- MK_COL(128u, 0u, 64u),
- MK_COL(128u, 0u, 128u),
- MK_COL(128u, 192u, 0u),
- MK_COL(128u, 192u, 192u),
- MK_COL(128u, 192u, 64u),
- MK_COL(128u, 192u, 128u),
- MK_COL(128u, 64u, 0u),
- MK_COL(128u, 64u, 192u),
- MK_COL(128u, 64u, 64u),
- MK_COL(128u, 64u, 128u),
- MK_COL(128u, 128u, 0u),
- MK_COL(128u, 128u, 192u),
- MK_COL(128u, 128u, 64u),
- MK_COL(128u, 128u, 128u),
-};
-
-#undef MK_COL
-
-//------------------------------------------------------------------------------
-// TODO(skal): move the functions to dsp/lossless.c when the correct
-// granularity is found. For now, we'll just copy-paste some useful bits
-// here instead.
-
-// In-place sum of each component with mod 256.
-static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) {
- const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u);
- const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu);
- *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
-}
-
-static WEBP_INLINE uint32_t Clip255(uint32_t a) {
- if (a < 256) {
- return a;
- }
- // return 0, when a is a negative integer.
- // return 255, when a is positive.
- return ~a >> 24;
-}
-
-// Delta palettization functions.
-static WEBP_INLINE int Square(int x) {
- return x * x;
-}
-
-static WEBP_INLINE uint32_t Intensity(uint32_t a) {
- return
- 30 * ((a >> 16) & 0xff) +
- 59 * ((a >> 8) & 0xff) +
- 11 * ((a >> 0) & 0xff);
-}
-
-static uint32_t CalcDist(uint32_t predicted_value, uint32_t actual_value,
- uint32_t palette_entry) {
- int i;
- uint32_t distance = 0;
- AddPixelsEq(&predicted_value, palette_entry);
- for (i = 0; i < 32; i += 8) {
- const int32_t av = (actual_value >> i) & 0xff;
- const int32_t pv = (predicted_value >> i) & 0xff;
- distance += Square(pv - av);
- }
- // We sum square of intensity difference with factor 10, but because Intensity
- // returns 100 times real intensity we need to multiply differences of colors
- // by 1000.
- distance *= 1000u;
- distance += Square(Intensity(predicted_value)
- - Intensity(actual_value));
- return distance;
-}
-
-static uint32_t Predict(int x, int y, uint32_t* image) {
- const uint32_t t = (y == 0) ? ARGB_BLACK : image[x];
- const uint32_t l = (x == 0) ? ARGB_BLACK : image[x - 1];
- const uint32_t p =
- (((((t >> 24) & 0xff) + ((l >> 24) & 0xff)) / 2) << 24) +
- (((((t >> 16) & 0xff) + ((l >> 16) & 0xff)) / 2) << 16) +
- (((((t >> 8) & 0xff) + ((l >> 8) & 0xff)) / 2) << 8) +
- (((((t >> 0) & 0xff) + ((l >> 0) & 0xff)) / 2) << 0);
- if (x == 0 && y == 0) return ARGB_BLACK;
- if (x == 0) return t;
- if (y == 0) return l;
- return p;
-}
-
-static WEBP_INLINE int AddSubtractComponentFullWithCoefficient(
- int a, int b, int c) {
- return Clip255(a + ((b - c) >> 2));
-}
-
-static WEBP_INLINE uint32_t ClampedAddSubtractFullWithCoefficient(
- uint32_t c0, uint32_t c1, uint32_t c2) {
- const int a = AddSubtractComponentFullWithCoefficient(
- c0 >> 24, c1 >> 24, c2 >> 24);
- const int r = AddSubtractComponentFullWithCoefficient((c0 >> 16) & 0xff,
- (c1 >> 16) & 0xff,
- (c2 >> 16) & 0xff);
- const int g = AddSubtractComponentFullWithCoefficient((c0 >> 8) & 0xff,
- (c1 >> 8) & 0xff,
- (c2 >> 8) & 0xff);
- const int b = AddSubtractComponentFullWithCoefficient(
- c0 & 0xff, c1 & 0xff, c2 & 0xff);
- return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
-}
-
-//------------------------------------------------------------------------------
-
-// Find palette entry with minimum error from difference of actual pixel value
-// and predicted pixel value. Propagate error of pixel to its top and left pixel
-// in src array. Write predicted_value + palette_entry to new_image. Return
-// index of best palette entry.
-static int FindBestPaletteEntry(uint32_t src, uint32_t predicted_value,
- const uint32_t palette[], int palette_size) {
- int i;
- int idx = 0;
- uint32_t best_distance = CalcDist(predicted_value, src, palette[0]);
- for (i = 1; i < palette_size; ++i) {
- const uint32_t distance = CalcDist(predicted_value, src, palette[i]);
- if (distance < best_distance) {
- best_distance = distance;
- idx = i;
- }
- }
- return idx;
-}
-
-static void ApplyBestPaletteEntry(int x, int y,
- uint32_t new_value, uint32_t palette_value,
- uint32_t* src, int src_stride,
- uint32_t* new_image) {
- AddPixelsEq(&new_value, palette_value);
- if (x > 0) {
- src[x - 1] = ClampedAddSubtractFullWithCoefficient(src[x - 1],
- new_value, src[x]);
- }
- if (y > 0) {
- src[x - src_stride] =
- ClampedAddSubtractFullWithCoefficient(src[x - src_stride],
- new_value, src[x]);
- }
- new_image[x] = new_value;
-}
-
-//------------------------------------------------------------------------------
-// Main entry point
-
-static WebPEncodingError ApplyDeltaPalette(uint32_t* src, uint32_t* dst,
- uint32_t src_stride,
- uint32_t dst_stride,
- const uint32_t* palette,
- int palette_size,
- int width, int height,
- int num_passes) {
- int x, y;
- WebPEncodingError err = VP8_ENC_OK;
- uint32_t* new_image = (uint32_t*)WebPSafeMalloc(width, sizeof(*new_image));
- uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row));
- if (new_image == NULL || tmp_row == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- while (num_passes--) {
- uint32_t* cur_src = src;
- uint32_t* cur_dst = dst;
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- const uint32_t predicted_value = Predict(x, y, new_image);
- tmp_row[x] = FindBestPaletteEntry(cur_src[x], predicted_value,
- palette, palette_size);
- ApplyBestPaletteEntry(x, y, predicted_value, palette[tmp_row[x]],
- cur_src, src_stride, new_image);
- }
- for (x = 0; x < width; ++x) {
- cur_dst[x] = palette[tmp_row[x]];
- }
- cur_src += src_stride;
- cur_dst += dst_stride;
- }
- }
- Error:
- WebPSafeFree(new_image);
- WebPSafeFree(tmp_row);
- return err;
-}
-
-// replaces enc->argb_ by a palettizable approximation of it,
-// and generates optimal enc->palette_[]
-WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) {
- const WebPPicture* const pic = enc->pic_;
- uint32_t* src = pic->argb;
- uint32_t* dst = enc->argb_;
- const int width = pic->width;
- const int height = pic->height;
-
- WebPEncodingError err = VP8_ENC_OK;
- memcpy(enc->palette_, kDeltaPalette, sizeof(kDeltaPalette));
- enc->palette_[DELTA_PALETTE_SIZE - 1] = src[0] - 0xff000000u;
- enc->palette_size_ = DELTA_PALETTE_SIZE;
- err = ApplyDeltaPalette(src, dst, pic->argb_stride, enc->current_width_,
- enc->palette_, enc->palette_size_,
- width, height, 2);
- if (err != VP8_ENC_OK) goto Error;
-
- Error:
- return err;
-}
-
-#else // !WEBP_EXPERIMENTAL_FEATURES
-
-WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) {
- (void)enc;
- return VP8_ENC_ERROR_INVALID_CONFIGURATION;
-}
-
-#endif // WEBP_EXPERIMENTAL_FEATURES
diff --git a/thirdparty/libwebp/src/enc/delta_palettization_enc.h b/thirdparty/libwebp/src/enc/delta_palettization_enc.h
deleted file mode 100644
index b15e2cd487..0000000000
--- a/thirdparty/libwebp/src/enc/delta_palettization_enc.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Mislav Bradac (mislavm@google.com)
-//
-
-#ifndef WEBP_ENC_DELTA_PALETTIZATION_ENC_H_
-#define WEBP_ENC_DELTA_PALETTIZATION_ENC_H_
-
-#include "src/webp/encode.h"
-#include "src/enc/vp8li_enc.h"
-
-// Replaces enc->argb_[] input by a palettizable approximation of it,
-// and generates optimal enc->palette_[].
-// This function can revert enc->use_palette_ / enc->use_predict_ flag
-// if delta-palettization is not producing expected saving.
-WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc);
-
-#endif // WEBP_ENC_DELTA_PALETTIZATION_ENC_H_
diff --git a/thirdparty/libwebp/src/enc/histogram_enc.c b/thirdparty/libwebp/src/enc/histogram_enc.c
index 9fdbc627a1..4e49e0a201 100644
--- a/thirdparty/libwebp/src/enc/histogram_enc.c
+++ b/thirdparty/libwebp/src/enc/histogram_enc.c
@@ -51,10 +51,12 @@ static void HistogramCopy(const VP8LHistogram* const src,
VP8LHistogram* const dst) {
uint32_t* const dst_literal = dst->literal_;
const int dst_cache_bits = dst->palette_code_bits_;
+ const int literal_size = VP8LHistogramNumCodes(dst_cache_bits);
const int histo_size = VP8LGetHistogramSize(dst_cache_bits);
assert(src->palette_code_bits_ == dst_cache_bits);
memcpy(dst, src, histo_size);
dst->literal_ = dst_literal;
+ memcpy(dst->literal_, src->literal_, literal_size * sizeof(*dst->literal_));
}
int VP8LGetHistogramSize(int cache_bits) {
@@ -91,9 +93,19 @@ void VP8LHistogramCreate(VP8LHistogram* const p,
VP8LHistogramStoreRefs(refs, p);
}
-void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits) {
+void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits,
+ int init_arrays) {
p->palette_code_bits_ = palette_code_bits;
- HistogramClear(p);
+ if (init_arrays) {
+ HistogramClear(p);
+ } else {
+ p->trivial_symbol_ = 0;
+ p->bit_cost_ = 0.;
+ p->literal_cost_ = 0.;
+ p->red_cost_ = 0.;
+ p->blue_cost_ = 0.;
+ memset(p->is_used_, 0, sizeof(p->is_used_));
+ }
}
VP8LHistogram* VP8LAllocateHistogram(int cache_bits) {
@@ -104,37 +116,70 @@ VP8LHistogram* VP8LAllocateHistogram(int cache_bits) {
histo = (VP8LHistogram*)memory;
// literal_ won't necessary be aligned.
histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
- VP8LHistogramInit(histo, cache_bits);
+ VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 0);
return histo;
}
+// Resets the pointers of the histograms to point to the bit buffer in the set.
+static void HistogramSetResetPointers(VP8LHistogramSet* const set,
+ int cache_bits) {
+ int i;
+ const int histo_size = VP8LGetHistogramSize(cache_bits);
+ uint8_t* memory = (uint8_t*) (set->histograms);
+ memory += set->max_size * sizeof(*set->histograms);
+ for (i = 0; i < set->max_size; ++i) {
+ memory = (uint8_t*) WEBP_ALIGN(memory);
+ set->histograms[i] = (VP8LHistogram*) memory;
+ // literal_ won't necessary be aligned.
+ set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
+ memory += histo_size;
+ }
+}
+
+// Returns the total size of the VP8LHistogramSet.
+static size_t HistogramSetTotalSize(int size, int cache_bits) {
+ const int histo_size = VP8LGetHistogramSize(cache_bits);
+ return (sizeof(VP8LHistogramSet) + size * (sizeof(VP8LHistogram*) +
+ histo_size + WEBP_ALIGN_CST));
+}
+
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) {
int i;
VP8LHistogramSet* set;
- const int histo_size = VP8LGetHistogramSize(cache_bits);
- const size_t total_size =
- sizeof(*set) + size * (sizeof(*set->histograms) +
- histo_size + WEBP_ALIGN_CST);
+ const size_t total_size = HistogramSetTotalSize(size, cache_bits);
uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory));
if (memory == NULL) return NULL;
set = (VP8LHistogramSet*)memory;
memory += sizeof(*set);
set->histograms = (VP8LHistogram**)memory;
- memory += size * sizeof(*set->histograms);
set->max_size = size;
set->size = size;
+ HistogramSetResetPointers(set, cache_bits);
for (i = 0; i < size; ++i) {
- memory = (uint8_t*)WEBP_ALIGN(memory);
- set->histograms[i] = (VP8LHistogram*)memory;
- // literal_ won't necessary be aligned.
- set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
- VP8LHistogramInit(set->histograms[i], cache_bits);
- memory += histo_size;
+ VP8LHistogramInit(set->histograms[i], cache_bits, /*init_arrays=*/ 0);
}
return set;
}
+void VP8LHistogramSetClear(VP8LHistogramSet* const set) {
+ int i;
+ const int cache_bits = set->histograms[0]->palette_code_bits_;
+ const int size = set->size;
+ const size_t total_size = HistogramSetTotalSize(size, cache_bits);
+ uint8_t* memory = (uint8_t*)set;
+
+ memset(memory, 0, total_size);
+ memory += sizeof(*set);
+ set->histograms = (VP8LHistogram**)memory;
+ set->max_size = size;
+ set->size = size;
+ HistogramSetResetPointers(set, cache_bits);
+ for (i = 0; i < size; ++i) {
+ set->histograms[i]->palette_code_bits_ = cache_bits;
+ }
+}
+
// -----------------------------------------------------------------------------
void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
@@ -237,7 +282,8 @@ static double FinalHuffmanCost(const VP8LStreaks* const stats) {
// Get the symbol entropy for the distribution 'population'.
// Set 'trivial_sym', if there's only one symbol present in the distribution.
static double PopulationCost(const uint32_t* const population, int length,
- uint32_t* const trivial_sym) {
+ uint32_t* const trivial_sym,
+ uint8_t* const is_used) {
VP8LBitEntropy bit_entropy;
VP8LStreaks stats;
VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats);
@@ -245,6 +291,8 @@ static double PopulationCost(const uint32_t* const population, int length,
*trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code
: VP8L_NON_TRIVIAL_SYM;
}
+ // The histogram is used if there is at least one non-zero streak.
+ *is_used = (stats.streaks[1][0] != 0 || stats.streaks[1][1] != 0);
return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
}
@@ -253,7 +301,9 @@ static double PopulationCost(const uint32_t* const population, int length,
// non-zero: both the zero-th one, or both the last one.
static WEBP_INLINE double GetCombinedEntropy(const uint32_t* const X,
const uint32_t* const Y,
- int length, int trivial_at_end) {
+ int length, int is_X_used,
+ int is_Y_used,
+ int trivial_at_end) {
VP8LStreaks stats;
if (trivial_at_end) {
// This configuration is due to palettization that transforms an indexed
@@ -262,28 +312,43 @@ static WEBP_INLINE double GetCombinedEntropy(const uint32_t* const X,
// Only FinalHuffmanCost needs to be evaluated.
memset(&stats, 0, sizeof(stats));
// Deal with the non-zero value at index 0 or length-1.
- stats.streaks[1][0] += 1;
+ stats.streaks[1][0] = 1;
// Deal with the following/previous zero streak.
- stats.counts[0] += 1;
- stats.streaks[0][1] += length - 1;
+ stats.counts[0] = 1;
+ stats.streaks[0][1] = length - 1;
return FinalHuffmanCost(&stats);
} else {
VP8LBitEntropy bit_entropy;
- VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats);
+ if (is_X_used) {
+ if (is_Y_used) {
+ VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats);
+ } else {
+ VP8LGetEntropyUnrefined(X, length, &bit_entropy, &stats);
+ }
+ } else {
+ if (is_Y_used) {
+ VP8LGetEntropyUnrefined(Y, length, &bit_entropy, &stats);
+ } else {
+ memset(&stats, 0, sizeof(stats));
+ stats.counts[0] = 1;
+ stats.streaks[0][length > 3] = length;
+ VP8LBitEntropyInit(&bit_entropy);
+ }
+ }
return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
}
}
// Estimates the Entropy + Huffman + other block overhead size cost.
-double VP8LHistogramEstimateBits(const VP8LHistogram* const p) {
+double VP8LHistogramEstimateBits(VP8LHistogram* const p) {
return
- PopulationCost(
- p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_), NULL)
- + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL)
+ PopulationCost(p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_),
+ NULL, &p->is_used_[0])
+ + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL, &p->is_used_[1])
+ + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL, &p->is_used_[2])
+ + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL, &p->is_used_[3])
+ + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL, &p->is_used_[4])
+ VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES)
+ VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES);
}
@@ -299,7 +364,8 @@ static int GetCombinedHistogramEntropy(const VP8LHistogram* const a,
int trivial_at_end = 0;
assert(a->palette_code_bits_ == b->palette_code_bits_);
*cost += GetCombinedEntropy(a->literal_, b->literal_,
- VP8LHistogramNumCodes(palette_code_bits), 0);
+ VP8LHistogramNumCodes(palette_code_bits),
+ a->is_used_[0], b->is_used_[0], 0);
*cost += VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES,
b->literal_ + NUM_LITERAL_CODES,
NUM_LENGTH_CODES);
@@ -319,19 +385,23 @@ static int GetCombinedHistogramEntropy(const VP8LHistogram* const a,
}
*cost +=
- GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES, trivial_at_end);
+ GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES, a->is_used_[1],
+ b->is_used_[1], trivial_at_end);
if (*cost > cost_threshold) return 0;
*cost +=
- GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES, trivial_at_end);
+ GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES, a->is_used_[2],
+ b->is_used_[2], trivial_at_end);
if (*cost > cost_threshold) return 0;
- *cost += GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES,
- trivial_at_end);
+ *cost +=
+ GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES,
+ a->is_used_[3], b->is_used_[3], trivial_at_end);
if (*cost > cost_threshold) return 0;
*cost +=
- GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES, 0);
+ GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES,
+ a->is_used_[4], b->is_used_[4], 0);
*cost +=
VP8LExtraCostCombined(a->distance_, b->distance_, NUM_DISTANCE_CODES);
if (*cost > cost_threshold) return 0;
@@ -419,16 +489,19 @@ static void UpdateDominantCostRange(
static void UpdateHistogramCost(VP8LHistogram* const h) {
uint32_t alpha_sym, red_sym, blue_sym;
const double alpha_cost =
- PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym);
+ PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym,
+ &h->is_used_[3]);
const double distance_cost =
- PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL) +
+ PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL, &h->is_used_[4]) +
VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES);
const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_);
- h->literal_cost_ = PopulationCost(h->literal_, num_codes, NULL) +
- VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES,
- NUM_LENGTH_CODES);
- h->red_cost_ = PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym);
- h->blue_cost_ = PopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym);
+ h->literal_cost_ =
+ PopulationCost(h->literal_, num_codes, NULL, &h->is_used_[0]) +
+ VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES);
+ h->red_cost_ =
+ PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym, &h->is_used_[1]);
+ h->blue_cost_ =
+ PopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym, &h->is_used_[2]);
h->bit_cost_ = h->literal_cost_ + h->red_cost_ + h->blue_cost_ +
alpha_cost + distance_cost;
if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) {
@@ -473,6 +546,7 @@ static void HistogramBuild(
VP8LHistogram** const histograms = image_histo->histograms;
VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs);
assert(histo_bits > 0);
+ VP8LHistogramSetClear(image_histo);
while (VP8LRefsCursorOk(&c)) {
const PixOrCopy* const v = c.cur_pos;
const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits);
@@ -493,11 +567,19 @@ static void HistogramCopyAndAnalyze(
const int histo_size = orig_histo->size;
VP8LHistogram** const orig_histograms = orig_histo->histograms;
VP8LHistogram** const histograms = image_histo->histograms;
+ image_histo->size = 0;
for (i = 0; i < histo_size; ++i) {
VP8LHistogram* const histo = orig_histograms[i];
UpdateHistogramCost(histo);
+
+ // Skip the histogram if it is completely empty, which can happen for tiles
+ // with no information (when they are skipped because of LZ77).
+ if (!histo->is_used_[0] && !histo->is_used_[1] && !histo->is_used_[2]
+ && !histo->is_used_[3] && !histo->is_used_[4]) {
+ continue;
+ }
// Copy histograms from orig_histo[] to image_histo[].
- HistogramCopy(histo, histograms[i]);
+ HistogramCopy(histo, histograms[image_histo->size++]);
}
}
@@ -674,6 +756,18 @@ static void HistoQueueUpdateHead(HistoQueue* const histo_queue,
}
}
+// Update the cost diff and combo of a pair of histograms. This needs to be
+// called when the the histograms have been merged with a third one.
+static void HistoQueueUpdatePair(const VP8LHistogram* const h1,
+ const VP8LHistogram* const h2,
+ double threshold,
+ HistogramPair* const pair) {
+ const double sum_cost = h1->bit_cost_ + h2->bit_cost_;
+ pair->cost_combo = 0.;
+ GetCombinedHistogramEntropy(h1, h2, sum_cost + threshold, &pair->cost_combo);
+ pair->cost_diff = pair->cost_combo - sum_cost;
+}
+
// Create a pair from indices "idx1" and "idx2" provided its cost
// is inferior to "threshold", a negative entropy.
// It returns the cost of the pair, or 0. if it superior to threshold.
@@ -683,7 +777,6 @@ static double HistoQueuePush(HistoQueue* const histo_queue,
const VP8LHistogram* h1;
const VP8LHistogram* h2;
HistogramPair pair;
- double sum_cost;
assert(threshold <= 0.);
if (idx1 > idx2) {
@@ -695,10 +788,8 @@ static double HistoQueuePush(HistoQueue* const histo_queue,
pair.idx2 = idx2;
h1 = histograms[idx1];
h2 = histograms[idx2];
- sum_cost = h1->bit_cost_ + h2->bit_cost_;
- pair.cost_combo = 0.;
- GetCombinedHistogramEntropy(h1, h2, sum_cost + threshold, &pair.cost_combo);
- pair.cost_diff = pair.cost_combo - sum_cost;
+
+ HistoQueueUpdatePair(h1, h2, threshold, &pair);
// Do not even consider the pair if it does not improve the entropy.
if (pair.cost_diff >= threshold) return 0.;
@@ -891,8 +982,7 @@ static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
}
if (do_eval) {
// Re-evaluate the cost of an updated pair.
- GetCombinedHistogramEntropy(histograms[p->idx1], histograms[p->idx2], 0,
- &p->cost_diff);
+ HistoQueueUpdatePair(histograms[p->idx1], histograms[p->idx2], 0., p);
if (p->cost_diff >= 0.) {
HistoQueuePopPair(&histo_queue, p);
continue;
@@ -987,8 +1077,7 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
// histograms of small sizes (as bin_map will be very sparse) and
// maximum quality q==100 (to preserve the compression gains at that level).
const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE;
- const int entropy_combine =
- (orig_histo->size > entropy_combine_num_bins * 2) && (quality < 100);
+ int entropy_combine;
if (orig_histo == NULL) goto Error;
@@ -996,15 +1085,16 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
HistogramBuild(xsize, histo_bits, refs, orig_histo);
// Copies the histograms and computes its bit_cost.
HistogramCopyAndAnalyze(orig_histo, image_histo);
-
+ entropy_combine =
+ (image_histo->size > entropy_combine_num_bins * 2) && (quality < 100);
if (entropy_combine) {
- const int bin_map_size = orig_histo->size;
+ const int bin_map_size = image_histo->size;
// Reuse histogram_symbols storage. By definition, it's guaranteed to be ok.
uint16_t* const bin_map = histogram_symbols;
const double combine_cost_factor =
GetCombineCostFactor(image_histo_raw_size, quality);
- HistogramAnalyzeEntropyBin(orig_histo, bin_map, low_effort);
+ HistogramAnalyzeEntropyBin(image_histo, bin_map, low_effort);
// Collapse histograms with similar entropy.
HistogramCombineEntropyBin(image_histo, tmp_histo, bin_map, bin_map_size,
entropy_combine_num_bins, combine_cost_factor,
diff --git a/thirdparty/libwebp/src/enc/histogram_enc.h b/thirdparty/libwebp/src/enc/histogram_enc.h
index e8c4c83f6f..54c2d21783 100644
--- a/thirdparty/libwebp/src/enc/histogram_enc.h
+++ b/thirdparty/libwebp/src/enc/histogram_enc.h
@@ -44,6 +44,7 @@ typedef struct {
double literal_cost_; // Cached values of dominant entropy costs:
double red_cost_; // literal, red & blue.
double blue_cost_;
+ uint8_t is_used_[5]; // 5 for literal, red, blue, alpha, distance
} VP8LHistogram;
// Collection of histograms with fixed capacity, allocated as one
@@ -67,7 +68,9 @@ void VP8LHistogramCreate(VP8LHistogram* const p,
int VP8LGetHistogramSize(int palette_code_bits);
// Set the palette_code_bits and reset the stats.
-void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits);
+// If init_arrays is true, the arrays are also filled with 0's.
+void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits,
+ int init_arrays);
// Collect all the references into a histogram (without reset)
void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
@@ -83,6 +86,9 @@ void VP8LFreeHistogramSet(VP8LHistogramSet* const histo);
// using 'cache_bits'. Return NULL in case of memory error.
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits);
+// Set the histograms in set to 0.
+void VP8LHistogramSetClear(VP8LHistogramSet* const set);
+
// Allocate and initialize histogram object with specified 'cache_bits'.
// Returns NULL in case of memory error.
// Special case of VP8LAllocateHistogramSet, with size equals 1.
@@ -113,7 +119,7 @@ double VP8LBitsEntropy(const uint32_t* const array, int n);
// Estimate how many bits the combined entropy of literals and distance
// approximately maps to.
-double VP8LHistogramEstimateBits(const VP8LHistogram* const p);
+double VP8LHistogramEstimateBits(VP8LHistogram* const p);
#ifdef __cplusplus
}
diff --git a/thirdparty/libwebp/src/enc/iterator_enc.c b/thirdparty/libwebp/src/enc/iterator_enc.c
index 7c47d51272..29f91d8315 100644
--- a/thirdparty/libwebp/src/enc/iterator_enc.c
+++ b/thirdparty/libwebp/src/enc/iterator_enc.c
@@ -128,7 +128,7 @@ static void ImportLine(const uint8_t* src, int src_stride,
for (; i < total_len; ++i) dst[i] = dst[len - 1];
}
-void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32) {
+void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32) {
const VP8Encoder* const enc = it->enc_;
const int x = it->x_, y = it->y_;
const WebPPicture* const pic = enc->pic_;
diff --git a/thirdparty/libwebp/src/enc/picture_tools_enc.c b/thirdparty/libwebp/src/enc/picture_tools_enc.c
index be292d4391..d0e8a495da 100644
--- a/thirdparty/libwebp/src/enc/picture_tools_enc.c
+++ b/thirdparty/libwebp/src/enc/picture_tools_enc.c
@@ -16,10 +16,6 @@
#include "src/enc/vp8i_enc.h"
#include "src/dsp/yuv.h"
-static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) {
- return (0xff000000u | (r << 16) | (g << 8) | b);
-}
-
//------------------------------------------------------------------------------
// Helper: clean up fully transparent area to help compressibility.
@@ -195,6 +191,10 @@ void WebPCleanupTransparentAreaLossless(WebPPicture* const pic) {
#define BLEND_10BIT(V0, V1, ALPHA) \
((((V0) * (1020 - (ALPHA)) + (V1) * (ALPHA)) * 0x101 + 1024) >> 18)
+static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) {
+ return (0xff000000u | (r << 16) | (g << 8) | b);
+}
+
void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) {
const int red = (background_rgb >> 16) & 0xff;
const int green = (background_rgb >> 8) & 0xff;
@@ -208,39 +208,44 @@ void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) {
const int U0 = VP8RGBToU(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF);
const int V0 = VP8RGBToV(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF);
const int has_alpha = pic->colorspace & WEBP_CSP_ALPHA_BIT;
- if (!has_alpha || pic->a == NULL) return; // nothing to do
+ uint8_t* y_ptr = pic->y;
+ uint8_t* u_ptr = pic->u;
+ uint8_t* v_ptr = pic->v;
+ uint8_t* a_ptr = pic->a;
+ if (!has_alpha || a_ptr == NULL) return; // nothing to do
for (y = 0; y < pic->height; ++y) {
// Luma blending
- uint8_t* const y_ptr = pic->y + y * pic->y_stride;
- uint8_t* const a_ptr = pic->a + y * pic->a_stride;
for (x = 0; x < pic->width; ++x) {
- const int alpha = a_ptr[x];
+ const uint8_t alpha = a_ptr[x];
if (alpha < 0xff) {
- y_ptr[x] = BLEND(Y0, y_ptr[x], a_ptr[x]);
+ y_ptr[x] = BLEND(Y0, y_ptr[x], alpha);
}
}
// Chroma blending every even line
if ((y & 1) == 0) {
- uint8_t* const u = pic->u + (y >> 1) * pic->uv_stride;
- uint8_t* const v = pic->v + (y >> 1) * pic->uv_stride;
uint8_t* const a_ptr2 =
(y + 1 == pic->height) ? a_ptr : a_ptr + pic->a_stride;
for (x = 0; x < uv_width; ++x) {
// Average four alpha values into a single blending weight.
// TODO(skal): might lead to visible contouring. Can we do better?
- const int alpha =
+ const uint32_t alpha =
a_ptr[2 * x + 0] + a_ptr[2 * x + 1] +
a_ptr2[2 * x + 0] + a_ptr2[2 * x + 1];
- u[x] = BLEND_10BIT(U0, u[x], alpha);
- v[x] = BLEND_10BIT(V0, v[x], alpha);
+ u_ptr[x] = BLEND_10BIT(U0, u_ptr[x], alpha);
+ v_ptr[x] = BLEND_10BIT(V0, v_ptr[x], alpha);
}
if (pic->width & 1) { // rightmost pixel
- const int alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]);
- u[x] = BLEND_10BIT(U0, u[x], alpha);
- v[x] = BLEND_10BIT(V0, v[x], alpha);
+ const uint32_t alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]);
+ u_ptr[x] = BLEND_10BIT(U0, u_ptr[x], alpha);
+ v_ptr[x] = BLEND_10BIT(V0, v_ptr[x], alpha);
}
+ } else {
+ u_ptr += pic->uv_stride;
+ v_ptr += pic->uv_stride;
}
- memset(a_ptr, 0xff, pic->width);
+ memset(a_ptr, 0xff, pic->width); // reset alpha value to opaque
+ a_ptr += pic->a_stride;
+ y_ptr += pic->y_stride;
}
} else {
uint32_t* argb = pic->argb;
diff --git a/thirdparty/libwebp/src/enc/vp8i_enc.h b/thirdparty/libwebp/src/enc/vp8i_enc.h
index 624e8f8e66..92439febb8 100644
--- a/thirdparty/libwebp/src/enc/vp8i_enc.h
+++ b/thirdparty/libwebp/src/enc/vp8i_enc.h
@@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define ENC_MAJ_VERSION 1
#define ENC_MIN_VERSION 0
-#define ENC_REV_VERSION 0
+#define ENC_REV_VERSION 1
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
@@ -278,7 +278,7 @@ int VP8IteratorIsDone(const VP8EncIterator* const it);
// Import uncompressed samples from source.
// If tmp_32 is not NULL, import boundary samples too.
// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory.
-void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32);
+void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32);
// export decimated samples
void VP8IteratorExport(const VP8EncIterator* const it);
// go to next macroblock. Returns false if not finished.
@@ -515,4 +515,4 @@ void WebPCleanupTransparentAreaLossless(WebPPicture* const pic);
} // extern "C"
#endif
-#endif /* WEBP_ENC_VP8I_ENC_H_ */
+#endif // WEBP_ENC_VP8I_ENC_H_
diff --git a/thirdparty/libwebp/src/enc/vp8l_enc.c b/thirdparty/libwebp/src/enc/vp8l_enc.c
index a89184eb08..2713edcd95 100644
--- a/thirdparty/libwebp/src/enc/vp8l_enc.c
+++ b/thirdparty/libwebp/src/enc/vp8l_enc.c
@@ -809,6 +809,7 @@ static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw,
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
goto Error;
}
+ VP8LHistogramSetClear(histogram_image);
// Build histogram image and symbols from backward references.
VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]);
@@ -1248,14 +1249,20 @@ static WebPEncodingError MakeInputImageCopy(VP8LEncoder* const enc) {
const WebPPicture* const picture = enc->pic_;
const int width = picture->width;
const int height = picture->height;
- int y;
+
err = AllocateTransformBuffer(enc, width, height);
if (err != VP8_ENC_OK) return err;
if (enc->argb_content_ == kEncoderARGB) return VP8_ENC_OK;
- for (y = 0; y < height; ++y) {
- memcpy(enc->argb_ + y * width,
- picture->argb + y * picture->argb_stride,
- width * sizeof(*enc->argb_));
+
+ {
+ uint32_t* dst = enc->argb_;
+ const uint32_t* src = picture->argb;
+ int y;
+ for (y = 0; y < height; ++y) {
+ memcpy(dst, src, width * sizeof(*dst));
+ dst += width;
+ src += picture->argb_stride;
+ }
}
enc->argb_content_ = kEncoderARGB;
assert(enc->current_width_ == width);
diff --git a/thirdparty/libwebp/src/enc/vp8li_enc.h b/thirdparty/libwebp/src/enc/vp8li_enc.h
index 298a4a0014..d2d0fc509c 100644
--- a/thirdparty/libwebp/src/enc/vp8li_enc.h
+++ b/thirdparty/libwebp/src/enc/vp8li_enc.h
@@ -115,4 +115,4 @@ void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
} // extern "C"
#endif
-#endif /* WEBP_ENC_VP8LI_ENC_H_ */
+#endif // WEBP_ENC_VP8LI_ENC_H_
diff --git a/thirdparty/libwebp/src/mux/animi.h b/thirdparty/libwebp/src/mux/animi.h
index 88899532aa..34c45ba4da 100644
--- a/thirdparty/libwebp/src/mux/animi.h
+++ b/thirdparty/libwebp/src/mux/animi.h
@@ -40,4 +40,4 @@ int WebPAnimEncoderRefineRect(
} // extern "C"
#endif
-#endif /* WEBP_MUX_ANIMI_H_ */
+#endif // WEBP_MUX_ANIMI_H_
diff --git a/thirdparty/libwebp/src/mux/muxedit.c b/thirdparty/libwebp/src/mux/muxedit.c
index 7a027b3cb4..ccf14b2a0c 100644
--- a/thirdparty/libwebp/src/mux/muxedit.c
+++ b/thirdparty/libwebp/src/mux/muxedit.c
@@ -69,12 +69,12 @@ void WebPMuxDelete(WebPMux* mux) {
if (idx == (INDEX)) { \
err = ChunkAssignData(&chunk, data, copy_data, tag); \
if (err == WEBP_MUX_OK) { \
- err = ChunkSetNth(&chunk, (LIST), nth); \
+ err = ChunkSetHead(&chunk, (LIST)); \
} \
return err; \
}
-static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, uint32_t nth,
+static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag,
const WebPData* const data, int copy_data) {
WebPChunk chunk;
WebPMuxError err = WEBP_MUX_NOT_FOUND;
@@ -190,7 +190,7 @@ WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4],
if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
// Add the given chunk.
- return MuxSet(mux, tag, 1, chunk_data, copy_data);
+ return MuxSet(mux, tag, chunk_data, copy_data);
}
// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'.
@@ -202,7 +202,7 @@ static WebPMuxError AddDataToChunkList(
ChunkInit(&chunk);
err = ChunkAssignData(&chunk, data, copy_data, tag);
if (err != WEBP_MUX_OK) goto Err;
- err = ChunkSetNth(&chunk, chunk_list, 1);
+ err = ChunkSetHead(&chunk, chunk_list);
if (err != WEBP_MUX_OK) goto Err;
return WEBP_MUX_OK;
Err:
@@ -266,14 +266,14 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
int copy_data) {
WebPMuxImage wpi;
WebPMuxError err;
- const WebPData* const bitstream = &info->bitstream;
// Sanity checks.
if (mux == NULL || info == NULL) return WEBP_MUX_INVALID_ARGUMENT;
if (info->id != WEBP_CHUNK_ANMF) return WEBP_MUX_INVALID_ARGUMENT;
- if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) {
+ if (info->bitstream.bytes == NULL ||
+ info->bitstream.size > MAX_CHUNK_PAYLOAD) {
return WEBP_MUX_INVALID_ARGUMENT;
}
@@ -287,7 +287,7 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
}
MuxImageInit(&wpi);
- err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi);
+ err = SetAlphaAndImageChunks(&info->bitstream, copy_data, &wpi);
if (err != WEBP_MUX_OK) goto Err;
assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful.
@@ -342,7 +342,7 @@ WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux,
// Set the animation parameters.
PutLE32(data, params->bgcolor);
PutLE16(data + 4, params->loop_count);
- return MuxSet(mux, kChunks[IDX_ANIM].tag, 1, &anim, 1);
+ return MuxSet(mux, kChunks[IDX_ANIM].tag, &anim, 1);
}
WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux,
@@ -540,7 +540,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
PutLE24(data + 4, width - 1); // canvas width.
PutLE24(data + 7, height - 1); // canvas height.
- return MuxSet(mux, kChunks[IDX_VP8X].tag, 1, &vp8x, 1);
+ return MuxSet(mux, kChunks[IDX_VP8X].tag, &vp8x, 1);
}
// Cleans up 'mux' by removing any unnecessary chunks.
diff --git a/thirdparty/libwebp/src/mux/muxi.h b/thirdparty/libwebp/src/mux/muxi.h
index 6b57eea30f..df9f74c63c 100644
--- a/thirdparty/libwebp/src/mux/muxi.h
+++ b/thirdparty/libwebp/src/mux/muxi.h
@@ -14,6 +14,7 @@
#ifndef WEBP_MUX_MUXI_H_
#define WEBP_MUX_MUXI_H_
+#include <assert.h>
#include <stdlib.h>
#include "src/dec/vp8i_dec.h"
#include "src/dec/vp8li_dec.h"
@@ -28,7 +29,7 @@ extern "C" {
#define MUX_MAJ_VERSION 1
#define MUX_MIN_VERSION 0
-#define MUX_REV_VERSION 0
+#define MUX_REV_VERSION 1
// Chunk object.
typedef struct WebPChunk WebPChunk;
@@ -126,11 +127,14 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag);
WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
int copy_data, uint32_t tag);
-// Sets 'chunk' at nth position in the 'chunk_list'.
-// nth = 0 has the special meaning "last of the list".
+// Sets 'chunk' as the only element in 'chunk_list' if it is empty.
// On success ownership is transferred from 'chunk' to the 'chunk_list'.
-WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
- uint32_t nth);
+WebPMuxError ChunkSetHead(WebPChunk* const chunk, WebPChunk** const chunk_list);
+// Sets 'chunk' at last position in the 'chunk_list'.
+// On success ownership is transferred from 'chunk' to the 'chunk_list'.
+// *chunk_list also points towards the last valid element of the initial
+// *chunk_list.
+WebPMuxError ChunkAppend(WebPChunk* const chunk, WebPChunk*** const chunk_list);
// Releases chunk and returns chunk->next_.
WebPChunk* ChunkRelease(WebPChunk* const chunk);
@@ -143,13 +147,13 @@ void ChunkListDelete(WebPChunk** const chunk_list);
// Returns size of the chunk including chunk header and padding byte (if any).
static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) {
+ assert(chunk_size <= MAX_CHUNK_PAYLOAD);
return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U);
}
// Size of a chunk including header and padding.
static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) {
const size_t data_size = chunk->data_.size;
- assert(data_size < MAX_CHUNK_PAYLOAD);
return SizeWithPadding(data_size);
}
@@ -227,4 +231,4 @@ WebPMuxError MuxValidate(const WebPMux* const mux);
} // extern "C"
#endif
-#endif /* WEBP_MUX_MUXI_H_ */
+#endif // WEBP_MUX_MUXI_H_
diff --git a/thirdparty/libwebp/src/mux/muxinternal.c b/thirdparty/libwebp/src/mux/muxinternal.c
index 1473f100e5..b9ee6717d3 100644
--- a/thirdparty/libwebp/src/mux/muxinternal.c
+++ b/thirdparty/libwebp/src/mux/muxinternal.c
@@ -111,27 +111,6 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
return ((nth > 0) && (iter > 0)) ? NULL : first;
}
-// Outputs a pointer to 'prev_chunk->next_',
-// where 'prev_chunk' is the pointer to the chunk at position (nth - 1).
-// Returns true if nth chunk was found.
-static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth,
- WebPChunk*** const location) {
- uint32_t count = 0;
- assert(chunk_list != NULL);
- *location = chunk_list;
-
- while (*chunk_list != NULL) {
- WebPChunk* const cur_chunk = *chunk_list;
- ++count;
- if (count == nth) return 1; // Found.
- chunk_list = &cur_chunk->next_;
- *location = chunk_list;
- }
-
- // *chunk_list is ok to be NULL if adding at last location.
- return (nth == 0 || (count == nth - 1)) ? 1 : 0;
-}
-
//------------------------------------------------------------------------------
// Chunk writer methods.
@@ -156,11 +135,12 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
return WEBP_MUX_OK;
}
-WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
- uint32_t nth) {
+WebPMuxError ChunkSetHead(WebPChunk* const chunk,
+ WebPChunk** const chunk_list) {
WebPChunk* new_chunk;
- if (!ChunkSearchListToSet(chunk_list, nth, &chunk_list)) {
+ assert(chunk_list != NULL);
+ if (*chunk_list != NULL) {
return WEBP_MUX_NOT_FOUND;
}
@@ -168,11 +148,26 @@ WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
*new_chunk = *chunk;
chunk->owner_ = 0;
- new_chunk->next_ = *chunk_list;
+ new_chunk->next_ = NULL;
*chunk_list = new_chunk;
return WEBP_MUX_OK;
}
+WebPMuxError ChunkAppend(WebPChunk* const chunk,
+ WebPChunk*** const chunk_list) {
+ assert(chunk_list != NULL && *chunk_list != NULL);
+
+ if (**chunk_list == NULL) {
+ ChunkSetHead(chunk, *chunk_list);
+ } else {
+ WebPChunk* last_chunk = **chunk_list;
+ while (last_chunk->next_ != NULL) last_chunk = last_chunk->next_;
+ ChunkSetHead(chunk, &last_chunk->next_);
+ *chunk_list = &last_chunk->next_;
+ }
+ return WEBP_MUX_OK;
+}
+
//------------------------------------------------------------------------------
// Chunk deletion method(s).
@@ -232,9 +227,11 @@ void MuxImageInit(WebPMuxImage* const wpi) {
WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) {
WebPMuxImage* next;
if (wpi == NULL) return NULL;
- ChunkDelete(wpi->header_);
- ChunkDelete(wpi->alpha_);
- ChunkDelete(wpi->img_);
+ // There should be at most one chunk of header_, alpha_, img_ but we call
+ // ChunkListDelete to be safe
+ ChunkListDelete(&wpi->header_);
+ ChunkListDelete(&wpi->alpha_);
+ ChunkListDelete(&wpi->img_);
ChunkListDelete(&wpi->unknown_);
next = wpi->next_;
diff --git a/thirdparty/libwebp/src/mux/muxread.c b/thirdparty/libwebp/src/mux/muxread.c
index 0b55286862..268f6acb53 100644
--- a/thirdparty/libwebp/src/mux/muxread.c
+++ b/thirdparty/libwebp/src/mux/muxread.c
@@ -59,6 +59,7 @@ static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk,
// Sanity checks.
if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA;
chunk_size = GetLE32(data + TAG_SIZE);
+ if (chunk_size > MAX_CHUNK_PAYLOAD) return WEBP_MUX_BAD_DATA;
{
const size_t chunk_disk_size = SizeWithPadding(chunk_size);
@@ -102,6 +103,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
const uint8_t* const last = bytes + size;
WebPChunk subchunk;
size_t subchunk_size;
+ WebPChunk** unknown_chunk_list = &wpi->unknown_;
ChunkInit(&subchunk);
assert(chunk->tag_ == kChunks[IDX_ANMF].tag);
@@ -116,7 +118,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
if (size < hdr_size) goto Fail;
ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_);
}
- ChunkSetNth(&subchunk, &wpi->header_, 1);
+ ChunkSetHead(&subchunk, &wpi->header_);
wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks.
// Rest of the chunks.
@@ -133,18 +135,23 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
switch (ChunkGetIdFromTag(subchunk.tag_)) {
case WEBP_CHUNK_ALPHA:
if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks.
- if (ChunkSetNth(&subchunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Fail;
+ if (ChunkSetHead(&subchunk, &wpi->alpha_) != WEBP_MUX_OK) goto Fail;
wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
break;
case WEBP_CHUNK_IMAGE:
- if (ChunkSetNth(&subchunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Fail;
+ if (wpi->img_ != NULL) goto Fail; // Only 1 image chunk allowed.
+ if (ChunkSetHead(&subchunk, &wpi->img_) != WEBP_MUX_OK) goto Fail;
if (!MuxImageFinalize(wpi)) goto Fail;
wpi->is_partial_ = 0; // wpi is completely filled.
break;
case WEBP_CHUNK_UNKNOWN:
- if (wpi->is_partial_) goto Fail; // Encountered an unknown chunk
- // before some image chunks.
- if (ChunkSetNth(&subchunk, &wpi->unknown_, 0) != WEBP_MUX_OK) goto Fail;
+ if (wpi->is_partial_) {
+ goto Fail; // Encountered an unknown chunk
+ // before some image chunks.
+ }
+ if (ChunkAppend(&subchunk, &unknown_chunk_list) != WEBP_MUX_OK) {
+ goto Fail;
+ }
break;
default:
goto Fail;
@@ -175,6 +182,9 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
const uint8_t* data;
size_t size;
WebPChunk chunk;
+ // Stores the end of the chunk lists so that it is faster to append data to
+ // their ends.
+ WebPChunk** chunk_list_ends[WEBP_CHUNK_NIL + 1] = { NULL };
ChunkInit(&chunk);
// Sanity checks.
@@ -187,7 +197,7 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
size = bitstream->size;
if (data == NULL) return NULL;
- if (size < RIFF_HEADER_SIZE) return NULL;
+ if (size < RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE) return NULL;
if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') ||
GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) {
return NULL;
@@ -196,8 +206,6 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
mux = WebPMuxNew();
if (mux == NULL) return NULL;
- if (size < RIFF_HEADER_SIZE + TAG_SIZE) goto Err;
-
tag = GetLE32(data + RIFF_HEADER_SIZE);
if (tag != kChunks[IDX_VP8].tag &&
tag != kChunks[IDX_VP8L].tag &&
@@ -205,13 +213,17 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
goto Err; // First chunk should be VP8, VP8L or VP8X.
}
- riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE));
- if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) {
- goto Err;
- } else {
- if (riff_size < size) { // Redundant data after last chunk.
- size = riff_size; // To make sure we don't read any data beyond mux_size.
- }
+ riff_size = GetLE32(data + TAG_SIZE);
+ if (riff_size > MAX_CHUNK_PAYLOAD) goto Err;
+
+ // Note this padding is historical and differs from demux.c which does not
+ // pad the file size.
+ riff_size = SizeWithPadding(riff_size);
+ if (riff_size < CHUNK_HEADER_SIZE) goto Err;
+ if (riff_size > size) goto Err;
+ // There's no point in reading past the end of the RIFF chunk.
+ if (size > riff_size + CHUNK_HEADER_SIZE) {
+ size = riff_size + CHUNK_HEADER_SIZE;
}
end = data + size;
@@ -226,7 +238,6 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
while (data != end) {
size_t data_size;
WebPChunkId id;
- WebPChunk** chunk_list;
if (ChunkVerifyAndAssign(&chunk, data, size, riff_size,
copy_data) != WEBP_MUX_OK) {
goto Err;
@@ -236,11 +247,11 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
switch (id) {
case WEBP_CHUNK_ALPHA:
if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks.
- if (ChunkSetNth(&chunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Err;
+ if (ChunkSetHead(&chunk, &wpi->alpha_) != WEBP_MUX_OK) goto Err;
wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
break;
case WEBP_CHUNK_IMAGE:
- if (ChunkSetNth(&chunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Err;
+ if (ChunkSetHead(&chunk, &wpi->img_) != WEBP_MUX_OK) goto Err;
if (!MuxImageFinalize(wpi)) goto Err;
wpi->is_partial_ = 0; // wpi is completely filled.
PushImage:
@@ -257,9 +268,13 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
default: // A non-image chunk.
if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before
// getting all chunks of an image.
- chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk.
- if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err;
+ if (chunk_list_ends[id] == NULL) {
+ chunk_list_ends[id] =
+ MuxGetChunkListFromId(mux, id); // List to add this chunk.
+ }
+ if (ChunkAppend(&chunk, &chunk_list_ends[id]) != WEBP_MUX_OK) goto Err;
if (id == WEBP_CHUNK_VP8X) { // grab global specs
+ if (data_size < CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE) goto Err;
mux->canvas_width_ = GetLE24(data + 12) + 1;
mux->canvas_height_ = GetLE24(data + 15) + 1;
}
@@ -385,6 +400,10 @@ static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size);
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
+ // There should be at most one alpha_ chunk and exactly one img_ chunk.
+ assert(wpi->alpha_ == NULL || wpi->alpha_->next_ == NULL);
+ assert(wpi->img_ != NULL && wpi->img_->next_ == NULL);
+
// Main RIFF header.
dst = MuxEmitRiffHeader(data, size);
diff --git a/thirdparty/libwebp/src/utils/bit_reader_inl_utils.h b/thirdparty/libwebp/src/utils/bit_reader_inl_utils.h
index 2ccc6ed326..7e607f370a 100644
--- a/thirdparty/libwebp/src/utils/bit_reader_inl_utils.h
+++ b/thirdparty/libwebp/src/utils/bit_reader_inl_utils.h
@@ -187,4 +187,4 @@ static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) {
} // extern "C"
#endif
-#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_
+#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/bit_reader_utils.h b/thirdparty/libwebp/src/utils/bit_reader_utils.h
index 04f9804409..de810d402a 100644
--- a/thirdparty/libwebp/src/utils/bit_reader_utils.h
+++ b/thirdparty/libwebp/src/utils/bit_reader_utils.h
@@ -182,4 +182,4 @@ static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) {
} // extern "C"
#endif
-#endif /* WEBP_UTILS_BIT_READER_UTILS_H_ */
+#endif // WEBP_UTILS_BIT_READER_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/bit_writer_utils.h b/thirdparty/libwebp/src/utils/bit_writer_utils.h
index 2cf5976fe3..b9d5102a5a 100644
--- a/thirdparty/libwebp/src/utils/bit_writer_utils.h
+++ b/thirdparty/libwebp/src/utils/bit_writer_utils.h
@@ -151,4 +151,4 @@ static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_BIT_WRITER_UTILS_H_ */
+#endif // WEBP_UTILS_BIT_WRITER_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/filters_utils.h b/thirdparty/libwebp/src/utils/filters_utils.h
index 410f2fcdf2..61da66e212 100644
--- a/thirdparty/libwebp/src/utils/filters_utils.h
+++ b/thirdparty/libwebp/src/utils/filters_utils.h
@@ -29,4 +29,4 @@ WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_FILTERS_UTILS_H_ */
+#endif // WEBP_UTILS_FILTERS_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c b/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c
index 3818a78b93..f65b6cdbb6 100644
--- a/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c
+++ b/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c
@@ -261,9 +261,15 @@ static void CleanupParams(SmoothParams* const p) {
int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
int strength) {
- const int radius = 4 * strength / 100;
+ int radius = 4 * strength / 100;
+
if (strength < 0 || strength > 100) return 0;
if (data == NULL || width <= 0 || height <= 0) return 0; // bad params
+
+ // limit the filter size to not exceed the image dimensions
+ if (2 * radius + 1 > width) radius = (width - 1) >> 1;
+ if (2 * radius + 1 > height) radius = (height - 1) >> 1;
+
if (radius > 0) {
SmoothParams p;
memset(&p, 0, sizeof(p));
diff --git a/thirdparty/libwebp/src/utils/quant_levels_dec_utils.h b/thirdparty/libwebp/src/utils/quant_levels_dec_utils.h
index f822107a72..327f19f336 100644
--- a/thirdparty/libwebp/src/utils/quant_levels_dec_utils.h
+++ b/thirdparty/libwebp/src/utils/quant_levels_dec_utils.h
@@ -32,4 +32,4 @@ int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ */
+#endif // WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/quant_levels_utils.h b/thirdparty/libwebp/src/utils/quant_levels_utils.h
index 75df2ba6a4..9ee3ea0075 100644
--- a/thirdparty/libwebp/src/utils/quant_levels_utils.h
+++ b/thirdparty/libwebp/src/utils/quant_levels_utils.h
@@ -33,4 +33,4 @@ int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_QUANT_LEVELS_UTILS_H_ */
+#endif // WEBP_UTILS_QUANT_LEVELS_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/random_utils.h b/thirdparty/libwebp/src/utils/random_utils.h
index 6d36c667e7..a5006f84f7 100644
--- a/thirdparty/libwebp/src/utils/random_utils.h
+++ b/thirdparty/libwebp/src/utils/random_utils.h
@@ -60,4 +60,4 @@ static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) {
} // extern "C"
#endif
-#endif /* WEBP_UTILS_RANDOM_UTILS_H_ */
+#endif // WEBP_UTILS_RANDOM_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/rescaler_utils.h b/thirdparty/libwebp/src/utils/rescaler_utils.h
index 8890e6fa13..ca41e42c4a 100644
--- a/thirdparty/libwebp/src/utils/rescaler_utils.h
+++ b/thirdparty/libwebp/src/utils/rescaler_utils.h
@@ -98,4 +98,4 @@ int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) {
} // extern "C"
#endif
-#endif /* WEBP_UTILS_RESCALER_UTILS_H_ */
+#endif // WEBP_UTILS_RESCALER_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/thread_utils.h b/thirdparty/libwebp/src/utils/thread_utils.h
index c8ae6c9033..29ad49f74b 100644
--- a/thirdparty/libwebp/src/utils/thread_utils.h
+++ b/thirdparty/libwebp/src/utils/thread_utils.h
@@ -87,4 +87,4 @@ WEBP_EXTERN const WebPWorkerInterface* WebPGetWorkerInterface(void);
} // extern "C"
#endif
-#endif /* WEBP_UTILS_THREAD_UTILS_H_ */
+#endif // WEBP_UTILS_THREAD_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/utils.h b/thirdparty/libwebp/src/utils/utils.h
index 52921bf24e..da97b5d38f 100644
--- a/thirdparty/libwebp/src/utils/utils.h
+++ b/thirdparty/libwebp/src/utils/utils.h
@@ -175,4 +175,4 @@ WEBP_EXTERN int WebPGetColorPalette(const struct WebPPicture* const pic,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_UTILS_H_ */
+#endif // WEBP_UTILS_UTILS_H_
diff --git a/thirdparty/libwebp/src/webp/decode.h b/thirdparty/libwebp/src/webp/decode.h
index 2165e96c95..95d31e7619 100644
--- a/thirdparty/libwebp/src/webp/decode.h
+++ b/thirdparty/libwebp/src/webp/decode.h
@@ -491,4 +491,4 @@ WEBP_EXTERN VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
} // extern "C"
#endif
-#endif /* WEBP_WEBP_DECODE_H_ */
+#endif // WEBP_WEBP_DECODE_H_
diff --git a/thirdparty/libwebp/src/webp/demux.h b/thirdparty/libwebp/src/webp/demux.h
index 555d641338..846eeb15a9 100644
--- a/thirdparty/libwebp/src/webp/demux.h
+++ b/thirdparty/libwebp/src/webp/demux.h
@@ -360,4 +360,4 @@ WEBP_EXTERN void WebPAnimDecoderDelete(WebPAnimDecoder* dec);
} // extern "C"
#endif
-#endif /* WEBP_WEBP_DEMUX_H_ */
+#endif // WEBP_WEBP_DEMUX_H_
diff --git a/thirdparty/libwebp/src/webp/encode.h b/thirdparty/libwebp/src/webp/encode.h
index 7ec3543dc2..549cf07730 100644
--- a/thirdparty/libwebp/src/webp/encode.h
+++ b/thirdparty/libwebp/src/webp/encode.h
@@ -542,4 +542,4 @@ WEBP_EXTERN int WebPEncode(const WebPConfig* config, WebPPicture* picture);
} // extern "C"
#endif
-#endif /* WEBP_WEBP_ENCODE_H_ */
+#endif // WEBP_WEBP_ENCODE_H_
diff --git a/thirdparty/libwebp/src/webp/format_constants.h b/thirdparty/libwebp/src/webp/format_constants.h
index 329fc8a3b0..eca6981a47 100644
--- a/thirdparty/libwebp/src/webp/format_constants.h
+++ b/thirdparty/libwebp/src/webp/format_constants.h
@@ -84,4 +84,4 @@ typedef enum {
// overflow a uint32_t.
#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1)
-#endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */
+#endif // WEBP_WEBP_FORMAT_CONSTANTS_H_
diff --git a/thirdparty/libwebp/src/webp/mux.h b/thirdparty/libwebp/src/webp/mux.h
index 28bb4a41c9..66096a92e0 100644
--- a/thirdparty/libwebp/src/webp/mux.h
+++ b/thirdparty/libwebp/src/webp/mux.h
@@ -527,4 +527,4 @@ WEBP_EXTERN void WebPAnimEncoderDelete(WebPAnimEncoder* enc);
} // extern "C"
#endif
-#endif /* WEBP_WEBP_MUX_H_ */
+#endif // WEBP_WEBP_MUX_H_
diff --git a/thirdparty/libwebp/src/webp/mux_types.h b/thirdparty/libwebp/src/webp/mux_types.h
index b37e2c67aa..ceea77dfc6 100644
--- a/thirdparty/libwebp/src/webp/mux_types.h
+++ b/thirdparty/libwebp/src/webp/mux_types.h
@@ -95,4 +95,4 @@ static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {
} // extern "C"
#endif
-#endif /* WEBP_WEBP_MUX_TYPES_H_ */
+#endif // WEBP_WEBP_MUX_TYPES_H_
diff --git a/thirdparty/libwebp/src/webp/types.h b/thirdparty/libwebp/src/webp/types.h
index 989a763f0d..0ce2622e41 100644
--- a/thirdparty/libwebp/src/webp/types.h
+++ b/thirdparty/libwebp/src/webp/types.h
@@ -49,4 +49,4 @@ typedef long long int int64_t;
// Macro to check ABI compatibility (same major revision number)
#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8))
-#endif /* WEBP_WEBP_TYPES_H_ */
+#endif // WEBP_WEBP_TYPES_H_
diff --git a/thirdparty/libwebsockets/core/context.c b/thirdparty/libwebsockets/core/context.c
index db9151b95f..7be004df33 100644
--- a/thirdparty/libwebsockets/core/context.c
+++ b/thirdparty/libwebsockets/core/context.c
@@ -134,7 +134,7 @@ lws_protocol_vh_priv_get(struct lws_vhost *vhost,
{
int n = 0;
- if (!vhost || !vhost->protocol_vh_privs)
+ if (!vhost || !vhost->protocol_vh_privs || !prot)
return NULL;
while (n < vhost->count_protocols && &vhost->protocols[n] != prot)
@@ -808,7 +808,7 @@ lws_create_vhost(struct lws_context *context,
#ifdef LWS_WITH_ACCESS_LOG
if (info->log_filepath) {
- vh->log_fd = open(info->log_filepath,
+ vh->log_fd = lws_open(info->log_filepath,
O_CREAT | O_APPEND | O_RDWR, 0600);
if (vh->log_fd == (int)LWS_INVALID_FILE) {
lwsl_err("unable to open log filepath %s\n",
@@ -936,24 +936,29 @@ lws_create_event_pipes(struct lws_context *context)
wsi->tsi = n;
wsi->vhost = NULL;
wsi->event_pipe = 1;
+ wsi->desc.sockfd = LWS_SOCK_INVALID;
+ context->pt[n].pipe_wsi = wsi;
+ context->count_wsi_allocated++;
- if (lws_plat_pipe_create(wsi)) {
- lws_free(wsi);
+ if (lws_plat_pipe_create(wsi))
+ /*
+ * platform code returns 0 if it actually created pipes
+ * and initialized pt->dummy_pipe_fds[]. If it used
+ * some other mechanism outside of signaling in the
+ * normal event loop, we skip treating the pipe as
+ * related to dummy_pipe_fds[], adding it to the fds,
+ * etc.
+ */
continue;
- }
+
wsi->desc.sockfd = context->pt[n].dummy_pipe_fds[0];
lwsl_debug("event pipe fd %d\n", wsi->desc.sockfd);
- context->pt[n].pipe_wsi = wsi;
-
if (context->event_loop_ops->accept)
context->event_loop_ops->accept(wsi);
if (__insert_wsi_socket_into_fds(context, wsi))
return 1;
-
- //lws_change_pollfd(context->pt[n].pipe_wsi, 0, LWS_POLLIN);
- context->count_wsi_allocated++;
}
return 0;
diff --git a/thirdparty/libwebsockets/core/libwebsockets.c b/thirdparty/libwebsockets/core/libwebsockets.c
index 0da02b17e4..58f00226f6 100644
--- a/thirdparty/libwebsockets/core/libwebsockets.c
+++ b/thirdparty/libwebsockets/core/libwebsockets.c
@@ -28,7 +28,7 @@
#ifdef LWS_WITH_IPV6
#if defined(WIN32) || defined(_WIN32)
#include <wincrypt.h>
-#include <Iphlpapi.h>
+#include <iphlpapi.h>
#else
#include <net/if.h>
#endif
@@ -58,6 +58,28 @@ static const char * const log_level_names[] = {
};
#endif
+int lws_open(const char *__file, int __oflag, ...)
+{
+ va_list ap;
+ int n;
+
+ va_start(ap, __oflag);
+ if (((__oflag & O_CREAT) == O_CREAT)
+#if defined(O_TMPFILE)
+ || ((__oflag & O_TMPFILE) == O_TMPFILE)
+#endif
+ )
+ /* last arg is really a mode_t. But windows... */
+ n = open(__file, __oflag, va_arg(ap, uint32_t));
+ else
+ n = open(__file, __oflag);
+ va_end(ap);
+
+ lws_plat_apply_FD_CLOEXEC(n);
+
+ return n;
+}
+
#if defined (_DEBUG)
void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role)
{
@@ -826,7 +848,15 @@ just_kill_connection:
if (!wsi->protocol)
pro = &wsi->vhost->protocols[0];
- pro->callback(wsi,
+ if (!wsi->upgraded_to_http2 || !lwsi_role_client(wsi))
+ /*
+ * The network wsi for a client h2 connection shouldn't
+ * call back for its role: the child stream connections
+ * own the role. Otherwise h2 will call back closed
+ * one too many times as the children do it and then
+ * the closing network stream.
+ */
+ pro->callback(wsi,
wsi->role_ops->close_cb[lwsi_role_server(wsi)],
wsi->user_space, NULL, 0);
wsi->told_user_closed = 1;
@@ -1453,7 +1483,7 @@ lws_vfs_select_fops(const struct lws_plat_file_ops *fops, const char *vfs_path,
pf = fops->next;
while (pf) {
n = 0;
- while (n < (int)ARRAY_SIZE(pf->fi) && pf->fi[n].sig) {
+ while (n < (int)LWS_ARRAY_SIZE(pf->fi) && pf->fi[n].sig) {
if (p >= vfs_path + pf->fi[n].len)
if (!strncmp(p - (pf->fi[n].len - 1),
pf->fi[n].sig,
@@ -1935,9 +1965,9 @@ static const char * const colours[] = {
"[32;1m", /* LLL_INFO */
"[34;1m", /* LLL_DEBUG */
"[33;1m", /* LLL_PARSER */
- "[33;1m", /* LLL_HEADER */
- "[33;1m", /* LLL_EXT */
- "[33;1m", /* LLL_CLIENT */
+ "[33m", /* LLL_HEADER */
+ "[33m", /* LLL_EXT */
+ "[33m", /* LLL_CLIENT */
"[33;1m", /* LLL_LATENCY */
"[30;1m", /* LLL_USER */
};
@@ -1946,14 +1976,14 @@ LWS_VISIBLE void lwsl_emit_stderr(int level, const char *line)
{
char buf[50];
static char tty = 3;
- int n, m = ARRAY_SIZE(colours) - 1;
+ int n, m = LWS_ARRAY_SIZE(colours) - 1;
if (!tty)
tty = isatty(2) | 2;
lwsl_timestamp(level, buf, sizeof(buf));
if (tty == 3) {
- n = 1 << (ARRAY_SIZE(colours) - 1);
+ n = 1 << (LWS_ARRAY_SIZE(colours) - 1);
while (n) {
if (level & n)
break;
@@ -2060,7 +2090,9 @@ lwsl_hexdump_level(int hexdump_level, const void *vbuf, size_t len)
LWS_VISIBLE void
lwsl_hexdump(const void *vbuf, size_t len)
{
+#if defined(_DEBUG)
lwsl_hexdump_level(LLL_DEBUG, vbuf, len);
+#endif
}
LWS_VISIBLE int
@@ -2091,6 +2123,8 @@ lws_partial_buffered(struct lws *wsi)
LWS_VISIBLE lws_fileofs_t
lws_get_peer_write_allowance(struct lws *wsi)
{
+ if (!wsi->role_ops->tx_credit)
+ return -1;
return wsi->role_ops->tx_credit(wsi);
}
@@ -3364,7 +3398,7 @@ lws_stats_log_dump(struct lws_context *context)
wl = pt->http.ah_wait_list;
while (wl) {
m++;
- wl = wl->ah_wait_list;
+ wl = wl->http.ah_wait_list;
}
lwsl_notice(" AH wait list count / actual: %d / %d\n",
@@ -3401,7 +3435,8 @@ lws_stats_log_dump(struct lws_context *context)
strcpy(buf, "unknown");
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
lwsl_notice(" peer %s: count wsi: %d, count ah: %d\n",
- buf, df->count_wsi, df->count_ah);
+ buf, df->count_wsi,
+ df->http.count_ah);
#else
lwsl_notice(" peer %s: count wsi: %d\n",
buf, df->count_wsi);
diff --git a/thirdparty/libwebsockets/core/output.c b/thirdparty/libwebsockets/core/output.c
index e2ff18ef27..11965a06b9 100644
--- a/thirdparty/libwebsockets/core/output.c
+++ b/thirdparty/libwebsockets/core/output.c
@@ -126,6 +126,18 @@ int lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len)
lwsl_info("** %p signalling to close now\n", wsi);
return -1; /* retry closing now */
}
+
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+#if !defined(LWS_WITHOUT_SERVER)
+ if (wsi->http.deferred_transaction_completed) {
+ lwsl_notice("%s: partial completed, doing "
+ "deferred transaction completed\n",
+ __func__);
+ wsi->http.deferred_transaction_completed = 0;
+ return lws_http_transaction_completed(wsi);
+ }
+#endif
+#endif
}
/* always callback on writeable */
lws_callback_on_writable(wsi);
diff --git a/thirdparty/libwebsockets/core/private.h b/thirdparty/libwebsockets/core/private.h
index d6b494ac8c..73748b0498 100644
--- a/thirdparty/libwebsockets/core/private.h
+++ b/thirdparty/libwebsockets/core/private.h
@@ -232,7 +232,7 @@
#endif
#else /* not windows */
- static inline int compatible_close(int fd) { return close(fd); }
+ static LWS_INLINE int compatible_close(int fd) { return close(fd); }
#include <sys/stat.h>
#include <sys/time.h>
@@ -351,7 +351,15 @@ extern "C" {
#define LWS_H2_RX_SCRATCH_SIZE 512
-
+#if defined(WIN32) || defined(_WIN32)
+ // Visual studio older than 2015 and WIN_CE has only _stricmp
+ #if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(_WIN32_WCE)
+ #define strcasecmp _stricmp
+ #elif !defined(__MINGW32__)
+ #define strcasecmp stricmp
+ #endif
+ #define getdtablesize() 30000
+#endif
/*
* All lws_tls...() functions must return this type, converting the
@@ -863,6 +871,7 @@ struct lws_context {
unsigned int timeout_secs;
unsigned int pt_serv_buf_size;
int max_http_header_data;
+ int max_http_header_pool;
int simultaneous_ssl_restriction;
int simultaneous_ssl;
#if defined(LWS_WITH_PEER_LIMITS)
@@ -889,7 +898,6 @@ struct lws_context {
volatile int service_tid;
int service_tid_detected;
- short max_http_header_pool;
short count_threads;
short plugin_protocol_count;
short plugin_extension_count;
@@ -1216,7 +1224,7 @@ LWS_EXTERN int
lws_rxflow_cache(struct lws *wsi, unsigned char *buf, int n, int len);
#ifndef LWS_LATENCY
-static inline void
+static LWS_INLINE void
lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
int ret, int completion) {
do {
@@ -1224,7 +1232,7 @@ lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
(void)completion;
} while (0);
}
-static inline void
+static LWS_INLINE void
lws_latency_pre(struct lws_context *context, struct lws *wsi) {
do { (void)context; (void)wsi; } while (0);
}
@@ -1597,6 +1605,9 @@ void lws_free(void *p);
#define lws_free_set_NULL(P) do { lws_realloc(P, 0, "free"); (P) = NULL; } while(0)
#endif
+char *
+lws_strdup(const char *s);
+
int
lws_plat_pipe_create(struct lws *wsi);
int
@@ -1606,6 +1617,9 @@ lws_plat_pipe_close(struct lws *wsi);
int
lws_create_event_pipes(struct lws_context *context);
+int lws_open(const char *__file, int __oflag, ...);
+void lws_plat_apply_FD_CLOEXEC(int n);
+
const struct lws_plat_file_ops *
lws_vfs_select_fops(const struct lws_plat_file_ops *fops, const char *vfs_path,
const char **vpath);
@@ -1673,10 +1687,10 @@ lws_broadcast(struct lws_context *context, int reason, void *in, size_t len);
lws_stats_atomic_max(struct lws_context * context,
struct lws_context_per_thread *pt, int index, uint64_t val);
#else
- static inline uint64_t lws_stats_atomic_bump(struct lws_context * context,
+ static LWS_INLINE uint64_t lws_stats_atomic_bump(struct lws_context * context,
struct lws_context_per_thread *pt, int index, uint64_t bump) {
(void)context; (void)pt; (void)index; (void)bump; return 0; }
- static inline uint64_t lws_stats_atomic_max(struct lws_context * context,
+ static LWS_INLINE uint64_t lws_stats_atomic_max(struct lws_context * context,
struct lws_context_per_thread *pt, int index, uint64_t val) {
(void)context; (void)pt; (void)index; (void)val; return 0; }
#endif
@@ -1703,6 +1717,11 @@ void
lws_peer_dump_from_wsi(struct lws *wsi);
#endif
+#ifdef LWS_WITH_HTTP_PROXY
+hubbub_error
+html_parser_cb(const hubbub_token *token, void *pw);
+#endif
+
void
__lws_remove_from_timeout_list(struct lws *wsi);
diff --git a/thirdparty/libwebsockets/libwebsockets.h b/thirdparty/libwebsockets/libwebsockets.h
index 7ae563d582..2c01696404 100644
--- a/thirdparty/libwebsockets/libwebsockets.h
+++ b/thirdparty/libwebsockets/libwebsockets.h
@@ -66,14 +66,6 @@ typedef unsigned long long lws_intptr_t;
#define O_RDONLY _O_RDONLY
#endif
-// Visual studio older than 2015 and WIN_CE has only _stricmp
-#if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(_WIN32_WCE)
-#define strcasecmp _stricmp
-#elif !defined(__MINGW32__)
-#define strcasecmp stricmp
-#endif
-#define getdtablesize() 30000
-
#define LWS_INLINE __inline
#define LWS_VISIBLE
#define LWS_WARN_UNUSED_RESULT
@@ -150,6 +142,7 @@ typedef unsigned long long lws_intptr_t;
#endif
#if defined(__ANDROID__)
+#include <netinet/in.h>
#include <unistd.h>
#define getdtablesize() sysconf(_SC_OPEN_MAX)
#endif
@@ -164,6 +157,9 @@ typedef unsigned long long lws_intptr_t;
#ifdef LWS_HAVE_UV_VERSION_H
#include <uv-version.h>
#endif
+#ifdef LWS_HAVE_NEW_UV_VERSION_H
+#include <uv/version.h>
+#endif
#endif /* LWS_WITH_LIBUV */
#if defined(LWS_WITH_LIBEVENT)
#include <event2/event.h>
@@ -456,9 +452,6 @@ lwsl_visible(int level);
#endif
struct lws;
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-#endif
typedef int64_t lws_usec_t;
@@ -540,7 +533,7 @@ struct timer_mapping {
#define lws_uv_getloop(a, b) (NULL)
-static inline void uv_timer_init(void *l, uv_timer_t *t)
+static LWS_INLINE void uv_timer_init(void *l, uv_timer_t *t)
{
(void)l;
*t = NULL;
@@ -548,7 +541,7 @@ static inline void uv_timer_init(void *l, uv_timer_t *t)
extern void esp32_uvtimer_cb(TimerHandle_t t);
-static inline void uv_timer_start(uv_timer_t *t, uv_cb_t *cb, int first, int rep)
+static LWS_INLINE void uv_timer_start(uv_timer_t *t, uv_cb_t *cb, int first, int rep)
{
struct timer_mapping *tm = (struct timer_mapping *)malloc(sizeof(*tm));
@@ -563,12 +556,12 @@ static inline void uv_timer_start(uv_timer_t *t, uv_cb_t *cb, int first, int rep
xTimerStart(*t, 0);
}
-static inline void uv_timer_stop(uv_timer_t *t)
+static LWS_INLINE void uv_timer_stop(uv_timer_t *t)
{
xTimerStop(*t, 0);
}
-static inline void uv_close(uv_handle_t *h, void *v)
+static LWS_INLINE void uv_close(uv_handle_t *h, void *v)
{
free(pvTimerGetTimerID((uv_timer_t)h));
xTimerDelete(*(uv_timer_t *)h, 0);
@@ -1757,7 +1750,7 @@ lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result);
* If the return is nonzero, it failed and there is nothing needing to be
* destroyed.
*/
-int
+LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
const uint8_t *key, size_t key_len);
@@ -1771,7 +1764,7 @@ lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
*
* If the return is nonzero, it failed and needs destroying.
*/
-int
+LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len);
/** lws_genhmac_destroy() - copy out the result digest and destroy the ctx
@@ -1785,7 +1778,7 @@ lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len);
* NULL result is supported so that you can destroy the ctx cleanly on error
* conditions, where there is no valid result.
*/
-int
+LWS_VISIBLE LWS_EXTERN int
lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result);
///@}
@@ -2812,7 +2805,7 @@ struct lws_context_creation_info {
/**< VHOST: pointer to optional linked list of per-vhost
* options made accessible to protocols */
int keepalive_timeout;
- /**< VHOST: (default = 0 = 60s) seconds to allow remote
+ /**< VHOST: (default = 0 = 5s) seconds to allow remote
* client to hold on to an idle HTTP/1.1 connection */
const char *log_filepath;
/**< VHOST: filepath to append logs to... this is opened before
@@ -4943,7 +4936,7 @@ lws_write(struct lws *wsi, unsigned char *buf, size_t len,
lws_write(wsi, (unsigned char *)(buf), len, LWS_WRITE_HTTP)
/* helper for multi-frame ws message flags */
-static inline int
+static LWS_INLINE int
lws_write_ws_flags(int initial, int is_start, int is_end)
{
int r;
@@ -5621,13 +5614,13 @@ struct lws_dll_lws { /* typed as struct lws * */
#define lws_dll_is_null(___dll) (!(___dll)->prev && !(___dll)->next)
-static inline void
+static LWS_INLINE void
lws_dll_lws_add_front(struct lws_dll_lws *_a, struct lws_dll_lws *_head)
{
lws_dll_add_front((struct lws_dll *)_a, (struct lws_dll *)_head);
}
-static inline void
+static LWS_INLINE void
lws_dll_lws_remove(struct lws_dll_lws *_a)
{
lws_dll_remove((struct lws_dll *)_a);
@@ -7064,9 +7057,6 @@ lws_email_destroy(struct lws_email *email);
//@{
struct lejp_ctx;
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0]))
-#endif
#define LWS_ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0]))
#define LEJP_FLAG_WS_KEEP 64
#define LEJP_FLAG_WS_COMMENTLINE 32
@@ -7219,7 +7209,7 @@ typedef signed char (*lejp_callback)(struct lejp_ctx *ctx, char reason);
#endif
#ifndef LEJP_STRING_CHUNK
/* must be >= 30 to assemble floats */
-#define LEJP_STRING_CHUNK 255
+#define LEJP_STRING_CHUNK 254
#endif
enum num_flags {
@@ -7253,7 +7243,7 @@ struct lejp_ctx {
uint16_t i[LEJP_MAX_INDEX_DEPTH]; /* index array */
uint16_t wild[LEJP_MAX_INDEX_DEPTH]; /* index array */
char path[LEJP_MAX_PATH];
- char buf[LEJP_STRING_CHUNK];
+ char buf[LEJP_STRING_CHUNK + 1];
/* int */
diff --git a/thirdparty/libwebsockets/lws_config.h b/thirdparty/libwebsockets/lws_config.h
index e5e15cc2fd..86ce9ac38a 100644
--- a/thirdparty/libwebsockets/lws_config.h
+++ b/thirdparty/libwebsockets/lws_config.h
@@ -174,7 +174,7 @@
#define LWS_HAVE_MALLOC_H
#endif
-#if !defined(IPHONE_ENABLED) && !defined(OSX_ENABLED) && !defined(__HAIKU__)
+#if !defined(__APPLE__) && !defined(__HAIKU__)
#define LWS_HAVE_PIPE2
#endif
diff --git a/thirdparty/libwebsockets/lws_config_private.h b/thirdparty/libwebsockets/lws_config_private.h
index b26d225afa..e531777624 100644
--- a/thirdparty/libwebsockets/lws_config_private.h
+++ b/thirdparty/libwebsockets/lws_config_private.h
@@ -81,7 +81,7 @@
/* Define to 1 if you have the <sys/prctl.h> header file. */
#define LWS_HAVE_SYS_PRCTL_H
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
#undef LWS_HAVE_SYS_PRCTL_H
#endif
diff --git a/thirdparty/libwebsockets/misc/lejp.c b/thirdparty/libwebsockets/misc/lejp.c
index 00d350f81e..99142b9553 100644
--- a/thirdparty/libwebsockets/misc/lejp.c
+++ b/thirdparty/libwebsockets/misc/lejp.c
@@ -20,6 +20,7 @@
*/
#include <libwebsockets.h>
+#include "core/private.h"
#include <string.h>
#include <stdio.h>
@@ -30,7 +31,7 @@
* \param callback: your user callback which will received parsed tokens
* \param user: optional user data pointer untouched by lejp
* \param paths: your array of name elements you are interested in
- * \param count_paths: ARRAY_SIZE() of @paths
+ * \param count_paths: LWS_ARRAY_SIZE() of @paths
*
* Prepares your context struct for use with lejp
*/
@@ -250,7 +251,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
case LEJP_MP_STRING:
if (c == '\"') {
- if (!ctx->sp) {
+ if (!ctx->sp) { /* JSON can't end on quote */
ret = LEJP_REJECT_MP_STRING_UNDERRUN;
goto reject;
}
@@ -417,7 +418,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
goto reject;
}
ctx->i[ctx->ipos++] = 0;
- if (ctx->ipos > ARRAY_SIZE(ctx->i)) {
+ if (ctx->ipos > LWS_ARRAY_SIZE(ctx->i)) {
ret = LEJP_REJECT_MP_DELIM_ISTACK;
goto reject;
}
@@ -425,17 +426,23 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
case ']':
/* pop */
+ if (!ctx->sp) { /* JSON can't end on ] */
+ ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
+ goto reject;
+ }
ctx->sp--;
if (ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END) {
ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY;
goto reject;
}
/* drop the path [n] bit */
- ctx->ppos = ctx->st[ctx->sp - 1].p;
- ctx->ipos = ctx->st[ctx->sp - 1].i;
+ if (ctx->sp) {
+ ctx->ppos = ctx->st[ctx->sp - 1].p;
+ ctx->ipos = ctx->st[ctx->sp - 1].i;
+ }
ctx->path[ctx->ppos] = '\0';
if (ctx->path_match &&
- ctx->ppos <= ctx->path_match_len)
+ ctx->ppos <= ctx->path_match_len)
/*
* we shrank the path to be
* smaller than the matching point
@@ -603,7 +610,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
break;
}
if (c == ']') {
- if (!ctx->sp) {
+ if (!ctx->sp) { /* JSON can't end on ] */
ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
goto reject;
}
@@ -631,7 +638,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
goto redo_character;
}
if (c == '}') {
- if (ctx->sp == 0) {
+ if (!ctx->sp) {
lejp_check_path_match(ctx);
if (ctx->callback(ctx, LEJPCB_OBJECT_END)) {
ret = LEJP_REJECT_CALLBACK;
@@ -716,7 +723,7 @@ add_stack_level:
ctx->st[ctx->sp].p = ctx->ppos;
ctx->st[ctx->sp].i = ctx->ipos;
- if (++ctx->sp == ARRAY_SIZE(ctx->st)) {
+ if (++ctx->sp == LWS_ARRAY_SIZE(ctx->st)) {
ret = LEJP_REJECT_STACK_OVERFLOW;
goto reject;
}
diff --git a/thirdparty/libwebsockets/plat/lws-plat-unix.c b/thirdparty/libwebsockets/plat/lws-plat-unix.c
index bacc6af647..7dba3bd82f 100644
--- a/thirdparty/libwebsockets/plat/lws-plat-unix.c
+++ b/thirdparty/libwebsockets/plat/lws-plat-unix.c
@@ -30,6 +30,12 @@
#endif
#include <dirent.h>
+void lws_plat_apply_FD_CLOEXEC(int n)
+{
+ if (n != -1)
+ fcntl(n, F_SETFD, FD_CLOEXEC );
+}
+
int
lws_plat_socket_offset(void)
{
@@ -330,6 +336,8 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd)
struct protoent *tcp_proto;
#endif
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+
if (vhost->ka_time) {
/* enable keepalive on this socket */
optval = 1;
@@ -952,7 +960,7 @@ lws_plat_write_file(const char *filename, void *buf, int len)
LWS_VISIBLE int
lws_plat_read_file(const char *filename, void *buf, int len)
{
- int n, fd = open(filename, O_RDONLY);
+ int n, fd = lws_open(filename, O_RDONLY);
if (fd == -1)
return -1;
diff --git a/thirdparty/libwebsockets/plat/lws-plat-win.c b/thirdparty/libwebsockets/plat/lws-plat-win.c
index 8a43081ef1..1850b64250 100644
--- a/thirdparty/libwebsockets/plat/lws-plat-win.c
+++ b/thirdparty/libwebsockets/plat/lws-plat-win.c
@@ -3,6 +3,10 @@
#endif
#include "core/private.h"
+void lws_plat_apply_FD_CLOEXEC(int n)
+{
+}
+
int
lws_plat_socket_offset(void)
{
@@ -54,7 +58,7 @@ time_in_microseconds()
memcpy(&datetime, &filetime, sizeof(datetime));
/* Windows file times are in 100s of nanoseconds. */
- return (datetime.QuadPart - DELTA_EPOCH_IN_MICROSECS) / 10;
+ return (datetime.QuadPart / 10) - DELTA_EPOCH_IN_MICROSECS;
}
#ifdef _WIN32_WCE
@@ -229,23 +233,21 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
continue;
wsi = wsi_from_fd(context, pfd->fd);
- if (wsi->listener)
+ if (!wsi || wsi->listener)
continue;
- if (!wsi || wsi->sock_send_blocking)
+ if (wsi->sock_send_blocking)
continue;
pfd->revents = LWS_POLLOUT;
n = lws_service_fd(context, pfd);
if (n < 0)
return -1;
+
+ /* Force WSAWaitForMultipleEvents() to check events and then return immediately. */
+ timeout_ms = 0;
+
/* if something closed, retry this slot */
if (n)
i--;
-
- /*
- * any wsi has truncated, force him signalled
- */
- if (wsi->trunc_len)
- WSASetEvent(pt->events[0]);
}
/*
@@ -261,9 +263,11 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
}
if (timeout_ms) {
+ lws_usec_t t;
+
lws_pt_lock(pt, __func__);
/* don't stay in poll wait longer than next hr timeout */
- lws_usec_t t = __lws_hrtimer_service(pt);
+ t = __lws_hrtimer_service(pt);
if ((lws_usec_t)timeout_ms * 1000 > t)
timeout_ms = (int)(t / 1000);
@@ -310,8 +314,10 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
if (pfd->revents & LWS_POLLHUP)
--eIdx;
- if (pfd->revents)
+ if (pfd->revents) {
+ recv(pfd->fd, NULL, 0, 0);
lws_service_fd_tsi(context, pfd, tsi);
+ }
}
}
@@ -637,7 +643,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
lws_fop_fd_t fop_fd;
FILE_STANDARD_INFO fInfo = {0};
- MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, ARRAY_SIZE(buf));
+ MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, LWS_ARRAY_SIZE(buf));
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0602 // Windows 8 (minimum when UWP_ENABLED, but can be used in Windows builds)
CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
@@ -810,7 +816,7 @@ lws_plat_write_file(const char *filename, void *buf, int len)
{
int m, fd;
- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ fd = lws_open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd == -1)
return -1;
@@ -824,7 +830,7 @@ lws_plat_write_file(const char *filename, void *buf, int len)
LWS_VISIBLE int
lws_plat_read_file(const char *filename, void *buf, int len)
{
- int n, fd = open(filename, O_RDONLY);
+ int n, fd = lws_open(filename, O_RDONLY);
if (fd == -1)
return -1;
diff --git a/thirdparty/libwebsockets/roles/h1/ops-h1.c b/thirdparty/libwebsockets/roles/h1/ops-h1.c
index d3b16f4d1f..9001c864ea 100644
--- a/thirdparty/libwebsockets/roles/h1/ops-h1.c
+++ b/thirdparty/libwebsockets/roles/h1/ops-h1.c
@@ -195,6 +195,7 @@ postbody_completion:
}
break;
+ case LRS_RETURNED_CLOSE:
case LRS_AWAITING_CLOSE_ACK:
case LRS_WAITING_TO_SEND_CLOSE:
case LRS_SHUTDOWN:
@@ -444,6 +445,16 @@ try_pollout:
if (lwsi_state(wsi) != LRS_ISSUING_FILE) {
+ if (wsi->trunc_len) {
+ //lwsl_notice("%s: completing partial\n", __func__);
+ if (lws_issue_raw(wsi, wsi->trunc_alloc + wsi->trunc_offset,
+ wsi->trunc_len) < 0) {
+ lwsl_info("%s signalling to close\n", __func__);
+ goto fail;
+ }
+ return LWS_HPI_RET_HANDLED;
+ }
+
lws_stats_atomic_bump(wsi->context, pt,
LWSSTATS_C_WRITEABLE_CB, 1);
#if defined(LWS_WITH_STATS)
@@ -655,6 +666,9 @@ rops_destroy_role_h1(struct lws *wsi)
ah = ah->next;
}
+#ifdef LWS_ROLE_WS
+ lws_free_set_NULL(wsi->ws);
+#endif
return 0;
}
diff --git a/thirdparty/libwebsockets/roles/http/client/client-handshake.c b/thirdparty/libwebsockets/roles/http/client/client-handshake.c
index 4830fc9eca..0095c79a69 100644
--- a/thirdparty/libwebsockets/roles/http/client/client-handshake.c
+++ b/thirdparty/libwebsockets/roles/http/client/client-handshake.c
@@ -162,7 +162,7 @@ create_new_conn:
if (!wsi->client_hostname_copy)
wsi->client_hostname_copy =
- strdup(lws_hdr_simple_ptr(wsi,
+ lws_strdup(lws_hdr_simple_ptr(wsi,
_WSI_TOKEN_CLIENT_PEER_ADDRESS));
/*
@@ -654,13 +654,13 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
lws_ssl_close(wsi);
#endif
+ __remove_wsi_socket_from_fds(wsi);
+
if (wsi->context->event_loop_ops->close_handle_manually)
wsi->context->event_loop_ops->close_handle_manually(wsi);
else
compatible_close(wsi->desc.sockfd);
- __remove_wsi_socket_from_fds(wsi);
-
#if defined(LWS_WITH_TLS)
wsi->tls.use_ssl = ssl;
#else
@@ -717,7 +717,7 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
}
#ifdef LWS_WITH_HTTP_PROXY
-static hubbub_error
+hubbub_error
html_parser_cb(const hubbub_token *token, void *pw)
{
struct lws_rewrite *r = (struct lws_rewrite *)pw;
@@ -846,7 +846,7 @@ html_parser_cb(const hubbub_token *token, void *pw)
#endif
-static char *
+char *
lws_strdup(const char *s)
{
char *d = lws_malloc(strlen(s) + 1, "strdup");
diff --git a/thirdparty/libwebsockets/roles/http/client/client.c b/thirdparty/libwebsockets/roles/http/client/client.c
index ce42dc6cd3..5645fa2b7a 100644
--- a/thirdparty/libwebsockets/roles/http/client/client.c
+++ b/thirdparty/libwebsockets/roles/http/client/client.c
@@ -93,7 +93,7 @@ lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd,
char *sb = p;
int n = 0;
#if defined(LWS_WITH_SOCKS5)
- char conn_mode = 0, pending_timeout = 0;
+ int conn_mode = 0, pending_timeout = 0;
#endif
if ((pollfd->revents & LWS_POLLOUT) &&
@@ -252,6 +252,8 @@ socks_reply_fail:
/* clear his proxy connection timeout */
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
goto start_ws_handshake;
+ default:
+ break;
}
break;
#endif
@@ -578,6 +580,8 @@ lws_http_transaction_completed_client(struct lws *wsi)
"queued client done");
}
+ _lws_header_table_reset(wsi->http.ah);
+
/* after the first one, they can only be coming from the queue */
wsi->transaction_from_pipeline_queue = 1;
@@ -629,12 +633,20 @@ lws_http_transaction_completed_client(struct lws *wsi)
}
LWS_VISIBLE LWS_EXTERN unsigned int
-lws_http_client_http_response(struct lws *wsi)
+lws_http_client_http_response(struct lws *_wsi)
{
- if (!wsi->http.ah)
- return 0;
+ struct lws *wsi;
+ unsigned int resp;
+
+ if (_wsi->http.ah && _wsi->http.ah->http_response)
+ return _wsi->http.ah->http_response;
- return wsi->http.ah->http_response;
+ lws_vhost_lock(_wsi->vhost);
+ wsi = _lws_client_wsi_master(_wsi);
+ resp = wsi->http.ah->http_response;
+ lws_vhost_unlock(_wsi->vhost);
+
+ return resp;
}
#endif
#if defined(LWS_PLAT_OPTEE)
@@ -781,7 +793,7 @@ lws_client_interpret_server_handshake(struct lws *wsi)
q = strrchr(new_path, '/');
if (q)
lws_strncpy(q + 1, p, sizeof(new_path) -
- (q - new_path));
+ (q - new_path) - 1);
else
path = p;
}
@@ -910,9 +922,9 @@ lws_client_interpret_server_handshake(struct lws *wsi)
* we seem to be good to go, give client last chance to check
* headers and OK it
*/
- if (wsi->protocol->callback(wsi,
+ if (w->protocol->callback(w,
LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
- wsi->user_space, NULL, 0)) {
+ w->user_space, NULL, 0)) {
cce = "HS: disallowed by client filter";
goto bail2;
@@ -924,9 +936,9 @@ lws_client_interpret_server_handshake(struct lws *wsi)
wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
/* call him back to inform him he is up */
- if (wsi->protocol->callback(wsi,
+ if (w->protocol->callback(w,
LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
- wsi->user_space, NULL, 0)) {
+ w->user_space, NULL, 0)) {
cce = "HS: disallowed at ESTABLISHED";
goto bail3;
}
@@ -964,9 +976,9 @@ bail2:
n = 0;
if (cce)
n = (int)strlen(cce);
- wsi->protocol->callback(wsi,
+ w->protocol->callback(w,
LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
- wsi->user_space, (void *)cce,
+ w->user_space, (void *)cce,
(unsigned int)n);
}
wsi->already_did_cce = 1;
@@ -1228,4 +1240,4 @@ completed:
return 0;
}
-#endif \ No newline at end of file
+#endif
diff --git a/thirdparty/libwebsockets/roles/http/header.c b/thirdparty/libwebsockets/roles/http/header.c
index 99e56f7564..dbcf27cbd1 100644
--- a/thirdparty/libwebsockets/roles/http/header.c
+++ b/thirdparty/libwebsockets/roles/http/header.c
@@ -26,7 +26,7 @@
const unsigned char *
lws_token_to_string(enum lws_token_indexes token)
{
- if ((unsigned int)token >= ARRAY_SIZE(set))
+ if ((unsigned int)token >= LWS_ARRAY_SIZE(set))
return NULL;
return (unsigned char *)set[token];
@@ -149,9 +149,17 @@ lws_add_http_common_headers(struct lws *wsi, unsigned int code,
(int)strlen(content_type), p, end))
return 1;
- if (content_len != LWS_ILLEGAL_HTTP_CONTENT_LEN &&
- lws_add_http_header_content_length(wsi, content_len, p, end))
- return 1;
+ if (content_len != LWS_ILLEGAL_HTTP_CONTENT_LEN) {
+ if (lws_add_http_header_content_length(wsi, content_len, p, end))
+ return 1;
+ } else {
+ if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
+ (unsigned char *)"close", 5,
+ p, end))
+ return 1;
+
+ wsi->http.connection_type = HTTP_CONNECTION_CLOSE;
+ }
return 0;
}
@@ -204,34 +212,40 @@ lws_add_http_header_status(struct lws *wsi, unsigned int _code,
#endif
#ifdef LWS_WITH_HTTP2
- if (lwsi_role_h2(wsi) || lwsi_role_h2_ENCAPSULATION(wsi))
- return lws_add_http2_header_status(wsi, code, p, end);
+ if (lwsi_role_h2(wsi) || lwsi_role_h2_ENCAPSULATION(wsi)) {
+ n = lws_add_http2_header_status(wsi, code, p, end);
+ if (n)
+ return n;
+ } else
#endif
- if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
- description = err400[code - 400];
- if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
- description = err500[code - 500];
-
- if (code == 100)
- description = "Continue";
- if (code == 200)
- description = "OK";
- if (code == 304)
- description = "Not Modified";
- else
- if (code >= 300 && code < 400)
- description = "Redirect";
-
- if (wsi->http.request_version < ARRAY_SIZE(hver))
- p1 = hver[wsi->http.request_version];
- else
- p1 = hver[0];
-
- n = sprintf((char *)code_and_desc, "%s %u %s", p1, code, description);
-
- if (lws_add_http_header_by_name(wsi, NULL, code_and_desc, n, p, end))
- return 1;
-
+ {
+ if (code >= 400 && code < (400 + LWS_ARRAY_SIZE(err400)))
+ description = err400[code - 400];
+ if (code >= 500 && code < (500 + LWS_ARRAY_SIZE(err500)))
+ description = err500[code - 500];
+
+ if (code == 100)
+ description = "Continue";
+ if (code == 200)
+ description = "OK";
+ if (code == 304)
+ description = "Not Modified";
+ else
+ if (code >= 300 && code < 400)
+ description = "Redirect";
+
+ if (wsi->http.request_version < LWS_ARRAY_SIZE(hver))
+ p1 = hver[wsi->http.request_version];
+ else
+ p1 = hver[0];
+
+ n = sprintf((char *)code_and_desc, "%s %u %s", p1, code,
+ description);
+
+ if (lws_add_http_header_by_name(wsi, NULL, code_and_desc, n, p,
+ end))
+ return 1;
+ }
headers = wsi->vhost->headers;
while (headers) {
if (lws_add_http_header_by_name(wsi,
diff --git a/thirdparty/libwebsockets/roles/http/private.h b/thirdparty/libwebsockets/roles/http/private.h
index 2aa7a92f75..5699914742 100644
--- a/thirdparty/libwebsockets/roles/http/private.h
+++ b/thirdparty/libwebsockets/roles/http/private.h
@@ -227,6 +227,7 @@ struct _lws_http_mode_related {
#if defined(LWS_WITH_HTTP_PROXY)
unsigned int perform_rewrite:1;
#endif
+ unsigned int deferred_transaction_completed:1;
};
diff --git a/thirdparty/libwebsockets/roles/http/server/lejp-conf.c b/thirdparty/libwebsockets/roles/http/server/lejp-conf.c
index e9ce854cfc..fbf10c288e 100644
--- a/thirdparty/libwebsockets/roles/http/server/lejp-conf.c
+++ b/thirdparty/libwebsockets/roles/http/server/lejp-conf.c
@@ -205,6 +205,7 @@ struct jpargs {
unsigned int enable_client_ssl:1;
unsigned int fresh_mount:1;
unsigned int any_vhosts:1;
+ unsigned int chunk:1;
};
static void *
@@ -213,6 +214,8 @@ lwsws_align(struct jpargs *a)
if ((lws_intptr_t)(a->p) & 15)
a->p += 16 - ((lws_intptr_t)(a->p) & 15);
+ a->chunk = 0;
+
return a->p;
}
@@ -225,7 +228,7 @@ arg_to_bool(const char *s)
if (n)
return 1;
- for (n = 0; n < (int)ARRAY_SIZE(on); n++)
+ for (n = 0; n < (int)LWS_ARRAY_SIZE(on); n++)
if (!strcasecmp(s, on[n]))
return 1;
@@ -413,25 +416,30 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
}
/* this catches, eg, vhosts[].headers[].xxx */
- if (reason == LEJPCB_VAL_STR_END &&
+ if ((reason == LEJPCB_VAL_STR_END || reason == LEJPCB_VAL_STR_CHUNK) &&
ctx->path_match == LEJPVP_HEADERS_NAME + 1) {
- headers = lwsws_align(a);
- a->p += sizeof(*headers);
-
- n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
- /* ie, enable this protocol, no options yet */
- headers->next = a->info->headers;
- a->info->headers = headers;
- headers->name = a->p;
- // lwsl_notice(" adding header %s=%s\n", a->p, ctx->buf);
- a->p += n - 1;
- *(a->p++) = ':';
- if (a->p < a->end)
- *(a->p++) = '\0';
- else
- *(a->p - 1) = '\0';
- headers->value = a->p;
- headers->options = NULL;
+ if (!a->chunk) {
+ headers = lwsws_align(a);
+ a->p += sizeof(*headers);
+
+ n = lejp_get_wildcard(ctx, 0, a->p,
+ lws_ptr_diff(a->end, a->p));
+ /* ie, add this header */
+ headers->next = a->info->headers;
+ a->info->headers = headers;
+ headers->name = a->p;
+
+ lwsl_notice(" adding header %s=%s\n", a->p, ctx->buf);
+ a->p += n - 1;
+ *(a->p++) = ':';
+ if (a->p < a->end)
+ *(a->p++) = '\0';
+ else
+ *(a->p - 1) = '\0';
+ headers->value = a->p;
+ headers->options = NULL;
+ }
+ a->chunk = reason == LEJPCB_VAL_STR_CHUNK;
goto dostring;
}
@@ -502,7 +510,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
if (a->last)
a->last->mount_next = m;
- for (n = 0; n < (int)ARRAY_SIZE(mount_protocols); n++)
+ for (n = 0; n < (int)LWS_ARRAY_SIZE(mount_protocols); n++)
if (!strncmp(a->m.origin, mount_protocols[n],
strlen(mount_protocols[n]))) {
lwsl_info("----%s\n", a->m.origin);
@@ -512,7 +520,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
break;
}
- if (n == (int)ARRAY_SIZE(mount_protocols)) {
+ if (n == (int)LWS_ARRAY_SIZE(mount_protocols)) {
lwsl_err("unsupported protocol:// %s\n", a->m.origin);
return 1;
}
@@ -750,6 +758,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
dostring:
p = ctx->buf;
+ p[LEJP_STRING_CHUNK] = '\0';
p1 = strstr(p, ESC_INSTALL_DATADIR);
if (p1) {
n = p1 - p;
@@ -762,7 +771,8 @@ dostring:
}
a->p += lws_snprintf(a->p, a->end - a->p, "%s", p);
- *(a->p)++ = '\0';
+ if (reason == LEJPCB_VAL_STR_END)
+ *(a->p)++ = '\0';
return 0;
}
@@ -779,7 +789,7 @@ lwsws_get_config(void *user, const char *f, const char * const *paths,
struct lejp_ctx ctx;
int n, m, fd;
- fd = open(f, O_RDONLY);
+ fd = lws_open(f, O_RDONLY);
if (fd < 0) {
lwsl_err("Cannot open %s\n", f);
return 2;
@@ -927,11 +937,11 @@ lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
if (lwsws_get_config(&a, dd, paths_global,
- ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
+ LWS_ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
return 1;
lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
if (lwsws_get_config_d(&a, dd, paths_global,
- ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
+ LWS_ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
return 1;
a.plugin_dirs[a.count_plugin_dirs] = NULL;
@@ -962,11 +972,11 @@ lwsws_get_config_vhosts(struct lws_context *context,
lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
if (lwsws_get_config(&a, dd, paths_vhosts,
- ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
+ LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
return 1;
lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
if (lwsws_get_config_d(&a, dd, paths_vhosts,
- ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
+ LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
return 1;
*cs = a.p;
diff --git a/thirdparty/libwebsockets/roles/http/server/parsers.c b/thirdparty/libwebsockets/roles/http/server/parsers.c
index cb022e362b..482bdc676a 100644
--- a/thirdparty/libwebsockets/roles/http/server/parsers.c
+++ b/thirdparty/libwebsockets/roles/http/server/parsers.c
@@ -563,7 +563,7 @@ int LWS_WARN_UNUSED_RESULT
lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s)
{
wsi->http.ah->nfrag++;
- if (wsi->http.ah->nfrag == ARRAY_SIZE(wsi->http.ah->frags)) {
+ if (wsi->http.ah->nfrag == LWS_ARRAY_SIZE(wsi->http.ah->frags)) {
lwsl_warn("More hdr frags than we can deal with, dropping\n");
return -1;
}
@@ -677,18 +677,16 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c)
return -1;
/* genuine delimiter */
if ((c == '&' || c == ';') && !enc) {
- if (issue_char(wsi, c) < 0)
+ if (issue_char(wsi, '\0') < 0)
return -1;
- /* swallow the terminator */
- ah->frags[ah->nfrag].len--;
/* link to next fragment */
ah->frags[ah->nfrag].nfrag = ah->nfrag + 1;
ah->nfrag++;
- if (ah->nfrag >= ARRAY_SIZE(ah->frags))
+ if (ah->nfrag >= LWS_ARRAY_SIZE(ah->frags))
goto excessive;
/* start next fragment after the & */
ah->post_literal_equal = 0;
- ah->frags[ah->nfrag].offset = ah->pos;
+ ah->frags[ah->nfrag].offset = ++ah->pos;
ah->frags[ah->nfrag].len = 0;
ah->frags[ah->nfrag].nfrag = 0;
goto swallow;
@@ -787,9 +785,9 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c)
/* move to using WSI_TOKEN_HTTP_URI_ARGS */
ah->nfrag++;
- if (ah->nfrag >= ARRAY_SIZE(ah->frags))
+ if (ah->nfrag >= LWS_ARRAY_SIZE(ah->frags))
goto excessive;
- ah->frags[ah->nfrag].offset = ah->pos;
+ ah->frags[ah->nfrag].offset = ++ah->pos;
ah->frags[ah->nfrag].len = 0;
ah->frags[ah->nfrag].nfrag = 0;
@@ -852,10 +850,10 @@ lws_parse(struct lws *wsi, unsigned char *buf, int *len)
c == ' ')
break;
- for (m = 0; m < ARRAY_SIZE(methods); m++)
+ for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
if (ah->parser_state == methods[m])
break;
- if (m == ARRAY_SIZE(methods))
+ if (m == LWS_ARRAY_SIZE(methods))
/* it was not any of the methods */
goto check_eol;
@@ -983,7 +981,7 @@ nope:
if (ah->lextable_pos < 0 && lwsi_role_h1(wsi) &&
lwsi_role_server(wsi)) {
/* this is not a header we know about */
- for (m = 0; m < ARRAY_SIZE(methods); m++)
+ for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
if (ah->frag_index[methods[m]]) {
/*
* already had the method, no idea what
@@ -996,7 +994,7 @@ nope:
* hm it's an unknown http method from a client in fact,
* it cannot be valid http
*/
- if (m == ARRAY_SIZE(methods)) {
+ if (m == LWS_ARRAY_SIZE(methods)) {
/*
* are we set up to accept raw in these cases?
*/
@@ -1025,7 +1023,7 @@ nope:
lextable[ah->lextable_pos + 1];
lwsl_parser("known hdr %d\n", n);
- for (m = 0; m < ARRAY_SIZE(methods); m++)
+ for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
if (n == methods[m] &&
ah->frag_index[methods[m]]) {
lwsl_warn("Duplicated method\n");
@@ -1061,7 +1059,7 @@ nope:
start_fragment:
ah->nfrag++;
excessive:
- if (ah->nfrag == ARRAY_SIZE(ah->frags)) {
+ if (ah->nfrag == LWS_ARRAY_SIZE(ah->frags)) {
lwsl_warn("More hdr frags than we can deal with\n");
return -1;
}
diff --git a/thirdparty/libwebsockets/roles/http/server/server.c b/thirdparty/libwebsockets/roles/http/server/server.c
index 350af3cd7e..abd86dc9b5 100644
--- a/thirdparty/libwebsockets/roles/http/server/server.c
+++ b/thirdparty/libwebsockets/roles/http/server/server.c
@@ -131,6 +131,17 @@ done_list:
(void)n;
#if defined(__linux__)
+#ifdef LWS_WITH_UNIX_SOCK
+ /*
+ * A Unix domain sockets cannot be bound for several times, even if we set
+ * the SO_REUSE* options on.
+ * However, fortunately, each thread is able to independently listen when
+ * running on a reasonably new Linux kernel. So we can safely assume
+ * creating just one listening socket for a multi-threaded environment won't
+ * fail in most cases.
+ */
+ if (!LWS_UNIX_SOCK_ENABLED(vhost))
+#endif
limit = vhost->context->count_threads;
#endif
@@ -694,7 +705,7 @@ lws_find_string_in_file(const char *filename, const char *string, int stringlen)
char buf[128];
int fd, match = 0, pos = 0, n = 0, hit = 0;
- fd = open(filename, O_RDONLY);
+ fd = lws_open(filename, O_RDONLY);
if (fd < 0) {
lwsl_err("can't open auth file: %s\n", filename);
return 0;
@@ -812,7 +823,7 @@ lws_http_get_uri_and_method(struct lws *wsi, char **puri_ptr, int *puri_len)
{
int n, count = 0;
- for (n = 0; n < (int)ARRAY_SIZE(methods); n++)
+ for (n = 0; n < (int)LWS_ARRAY_SIZE(methods); n++)
if (lws_hdr_total_length(wsi, methods[n]))
count++;
if (!count) {
@@ -827,7 +838,7 @@ lws_http_get_uri_and_method(struct lws *wsi, char **puri_ptr, int *puri_len)
return -1;
}
- for (n = 0; n < (int)ARRAY_SIZE(methods); n++)
+ for (n = 0; n < (int)LWS_ARRAY_SIZE(methods); n++)
if (lws_hdr_total_length(wsi, methods[n])) {
*puri_ptr = lws_hdr_simple_ptr(wsi, methods[n]);
*puri_len = lws_hdr_total_length(wsi, methods[n]);
@@ -857,7 +868,7 @@ lws_http_action(struct lws *wsi)
};
meth = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len);
- if (meth < 0 || meth >= (int)ARRAY_SIZE(method_names))
+ if (meth < 0 || meth >= (int)LWS_ARRAY_SIZE(method_names))
goto bail_nuke_ah;
/* we insist on absolute paths */
@@ -1128,7 +1139,7 @@ lws_http_action(struct lws *wsi)
}
if (pcolon > pslash)
pcolon = NULL;
-
+
if (pcolon)
n = pcolon - hit->origin;
else
@@ -1142,13 +1153,13 @@ lws_http_action(struct lws *wsi)
i.address = ads;
i.port = 80;
- if (hit->origin_protocol == LWSMPRO_HTTPS) {
+ if (hit->origin_protocol == LWSMPRO_HTTPS) {
i.port = 443;
i.ssl_connection = 1;
}
if (pcolon)
i.port = atoi(pcolon + 1);
-
+
lws_snprintf(rpath, sizeof(rpath) - 1, "/%s/%s", pslash + 1,
uri_ptr + hit->mountpoint_len);
lws_clean_url(rpath);
@@ -1164,7 +1175,7 @@ lws_http_action(struct lws *wsi)
p++;
}
}
-
+
i.path = rpath;
i.host = i.address;
@@ -1178,7 +1189,7 @@ lws_http_action(struct lws *wsi)
"from %s, to %s\n",
i.address, i.port, i.path, i.ssl_connection,
i.uri_replace_from, i.uri_replace_to);
-
+
if (!lws_client_connect_via_info(&i)) {
lwsl_err("proxy connect fail\n");
return 1;
@@ -1714,12 +1725,31 @@ lws_http_transaction_completed(struct lws *wsi)
{
int n = NO_PENDING_TIMEOUT;
+ if (wsi->trunc_len) {
+ /*
+ * ...so he tried to send something large as the http reply,
+ * it went as a partial, but he immediately said the
+ * transaction was completed.
+ *
+ * Defer the transaction completed until the last part of the
+ * partial is sent.
+ */
+ lwsl_notice("%s: deferring due to partial\n", __func__);
+ wsi->http.deferred_transaction_completed = 1;
+
+ return 0;
+ }
+
lwsl_info("%s: wsi %p\n", __func__, wsi);
lws_access_log(wsi);
if (!wsi->hdr_parsing_completed) {
- lwsl_notice("%s: ignoring, ah parsing incomplete\n", __func__);
+ char peer[64];
+ lws_get_peer_simple(wsi, peer, sizeof(peer) - 1);
+ peer[sizeof(peer) - 1] = '\0';
+ lwsl_notice("%s: (from %s) ignoring, ah parsing incomplete\n",
+ __func__, peer);
return 0;
}
diff --git a/thirdparty/libwebsockets/roles/ws/client-parser-ws.c b/thirdparty/libwebsockets/roles/ws/client-parser-ws.c
index aa561ce034..7287fb1590 100644
--- a/thirdparty/libwebsockets/roles/ws/client-parser-ws.c
+++ b/thirdparty/libwebsockets/roles/ws/client-parser-ws.c
@@ -450,7 +450,7 @@ ping_drop:
break;
case LWSWSOPC_PONG:
- lwsl_info("client receied pong\n");
+ lwsl_info("client received pong\n");
lwsl_hexdump(&wsi->ws->rx_ubuf[LWS_PRE],
wsi->ws->rx_ubuf_head);
@@ -488,9 +488,6 @@ ping_drop:
ebuf.token = &wsi->ws->rx_ubuf[LWS_PRE];
ebuf.len = wsi->ws->rx_ubuf_head;
- if (wsi->ws->opcode == LWSWSOPC_PONG && !ebuf.len)
- goto already_done;
-
#if !defined(LWS_WITHOUT_EXTENSIONS)
drain_extension:
lwsl_ext("%s: passing %d to ext\n", __func__, ebuf.len);
@@ -504,14 +501,12 @@ drain_extension:
#endif
lwsl_debug("post inflate ebuf len %d\n", ebuf.len);
- if (
#if !defined(LWS_WITHOUT_EXTENSIONS)
- rx_draining_ext &&
-#endif
- !ebuf.len) {
+ if (rx_draining_ext && !ebuf.len) {
lwsl_debug(" --- ending drain on 0 read result\n");
goto already_done;
}
+#endif
if (wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
if (lws_check_utf8(&wsi->ws->utf8,
diff --git a/thirdparty/libwebsockets/roles/ws/ops-ws.c b/thirdparty/libwebsockets/roles/ws/ops-ws.c
index 5ddaba9e18..665b2c9b74 100644
--- a/thirdparty/libwebsockets/roles/ws/ops-ws.c
+++ b/thirdparty/libwebsockets/roles/ws/ops-ws.c
@@ -1246,8 +1246,7 @@ int rops_handle_POLLOUT_ws(struct lws *wsi)
return LWS_HP_RET_BAIL_OK;
}
- if (lwsi_role_client(wsi) && !wsi->socket_is_permanently_unusable &&
- wsi->ws->send_check_ping) {
+ if (!wsi->socket_is_permanently_unusable && wsi->ws->send_check_ping) {
lwsl_info("issuing ping on wsi %p\n", wsi);
wsi->ws->send_check_ping = 0;
@@ -1282,7 +1281,7 @@ int rops_handle_POLLOUT_ws(struct lws *wsi)
* payload ordering, but since they are always complete
* fragments control packets can interleave OK.
*/
- if (lwsi_role_client(wsi) && wsi->ws->tx_draining_ext) {
+ if (wsi->ws->tx_draining_ext) {
lwsl_ext("SERVICING TX EXT DRAINING\n");
if (lws_write(wsi, NULL, 0, LWS_WRITE_CONTINUATION) < 0)
return LWS_HP_RET_BAIL_DIE;
@@ -1292,8 +1291,10 @@ int rops_handle_POLLOUT_ws(struct lws *wsi)
/* Priority 6: extensions
*/
- if (!wsi->ws->extension_data_pending)
+ if (!wsi->ws->extension_data_pending && !wsi->ws->tx_draining_ext) {
+ lwsl_ext("%s: !wsi->ws->extension_data_pending\n", __func__);
return LWS_HP_RET_USER_SERVICE;
+ }
/*
* check in on the active extensions, see if they
@@ -1412,15 +1413,13 @@ rops_periodic_checks_ws(struct lws_context *context, int tsi, time_t now)
wsi->ws->time_next_ping_check) >
context->ws_ping_pong_interval) {
- lwsl_info("req pp on wsi %p\n",
- wsi);
+ lwsl_info("req pp on wsi %p\n", wsi);
wsi->ws->send_check_ping = 1;
lws_set_timeout(wsi,
PENDING_TIMEOUT_WS_PONG_CHECK_SEND_PING,
context->timeout_secs);
lws_callback_on_writable(wsi);
- wsi->ws->time_next_ping_check =
- now;
+ wsi->ws->time_next_ping_check = now;
}
wsi = wsi->same_vh_protocol_next;
}
@@ -1466,6 +1465,9 @@ rops_service_flag_pending_ws(struct lws_context *context, int tsi)
static int
rops_close_via_role_protocol_ws(struct lws *wsi, enum lws_close_status reason)
{
+ if (!wsi->ws)
+ return 0;
+
if (!wsi->ws->close_in_ping_buffer_len && /* already a reason */
(reason == LWS_CLOSE_STATUS_NOSTATUS ||
reason == LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY))
@@ -1512,7 +1514,7 @@ rops_close_role_ws(struct lws_context_per_thread *pt, struct lws *wsi)
if (wsi->ws->tx_draining_ext) {
struct lws **w = &pt->ws.tx_draining_ext_list;
- lwsl_notice("%s: CLEARING tx_draining_ext\n", __func__);
+ lwsl_ext("%s: CLEARING tx_draining_ext\n", __func__);
wsi->ws->tx_draining_ext = 0;
/* remove us from context draining ext list */
while (*w) {
@@ -1563,7 +1565,7 @@ rops_write_role_protocol_ws(struct lws *wsi, unsigned char *buf, size_t len,
/* remove us from the list */
struct lws **w = &pt->ws.tx_draining_ext_list;
- lwsl_notice("%s: CLEARING tx_draining_ext\n", __func__);
+ lwsl_ext("%s: CLEARING tx_draining_ext\n", __func__);
wsi->ws->tx_draining_ext = 0;
/* remove us from context draining ext list */
while (*w) {
@@ -1588,7 +1590,7 @@ rops_write_role_protocol_ws(struct lws *wsi, unsigned char *buf, size_t len,
if (!(wpt & LWS_WRITE_NO_FIN) && len)
*wp &= ~LWS_WRITE_NO_FIN;
- lwsl_notice("FORCED draining wp to 0x%02X (stashed 0x%02X, incoming 0x%02X)\n", *wp,
+ lwsl_ext("FORCED draining wp to 0x%02X (stashed 0x%02X, incoming 0x%02X)\n", *wp,
wsi->ws->tx_draining_stashed_wp, wpt);
// assert(0);
}
@@ -1644,7 +1646,7 @@ rops_write_role_protocol_ws(struct lws *wsi, unsigned char *buf, size_t len,
// lwsl_notice("ext processed %d plaintext into %d compressed (wp 0x%x)\n", m, (int)ebuf.len, *wp);
if (n && ebuf.len) {
- lwsl_notice("write drain len %d (wp 0x%x) SETTING tx_draining_ext\n", (int)ebuf.len, *wp);
+ lwsl_ext("write drain len %d (wp 0x%x) SETTING tx_draining_ext\n", (int)ebuf.len, *wp);
/* extension requires further draining */
wsi->ws->tx_draining_ext = 1;
wsi->ws->tx_draining_ext_list = pt->ws.tx_draining_ext_list;
diff --git a/thirdparty/libwebsockets/tls/mbedtls/mbedtls-server.c b/thirdparty/libwebsockets/tls/mbedtls/mbedtls-server.c
index 2de6d422e3..f17c7e5494 100644
--- a/thirdparty/libwebsockets/tls/mbedtls/mbedtls-server.c
+++ b/thirdparty/libwebsockets/tls/mbedtls/mbedtls-server.c
@@ -631,7 +631,7 @@ lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
/* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */
- for (n = 0; n < (int)ARRAY_SIZE(x5); n++) {
+ for (n = 0; n < (int)LWS_ARRAY_SIZE(x5); n++) {
if (p != subject)
*p++ = ',';
if (elements[n])
diff --git a/thirdparty/libwebsockets/tls/mbedtls/ssl.c b/thirdparty/libwebsockets/tls/mbedtls/ssl.c
index 6ae9d2556b..f311ef50e3 100644
--- a/thirdparty/libwebsockets/tls/mbedtls/ssl.c
+++ b/thirdparty/libwebsockets/tls/mbedtls/ssl.c
@@ -121,8 +121,6 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
if (wsi->vhost)
wsi->vhost->conn_stats.rx += n;
- lws_restart_ws_ping_pong_timer(wsi);
-
/*
* if it was our buffer that limited what we read,
* check if SSL has additional data pending inside SSL buffers.
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_types.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_types.h
index ba19663d9e..68ac748a28 100644
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_types.h
+++ b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_types.h
@@ -37,7 +37,11 @@ typedef void RSA;
typedef void STACK;
typedef void BIO;
+#if defined(WIN32) || defined(_WIN32)
+#define ossl_inline __inline
+#else
#define ossl_inline inline
+#endif
#define SSL_METHOD_CALL(f, s, ...) s->method->func->ssl_##f(s, ##__VA_ARGS__)
#define X509_METHOD_CALL(f, x, ...) x->method->x509_##f(x, ##__VA_ARGS__)
diff --git a/thirdparty/libwebsockets/uwp_fixes.diff b/thirdparty/libwebsockets/uwp_fixes.diff
index 5b9d8724ed..21c3275bba 100644
--- a/thirdparty/libwebsockets/uwp_fixes.diff
+++ b/thirdparty/libwebsockets/uwp_fixes.diff
@@ -1,15 +1,15 @@
diff --git a/thirdparty/libwebsockets/plat/lws-plat-win.c b/thirdparty/libwebsockets/plat/lws-plat-win.c
-index 948db6289..511e29739 100644
+index bd513b494..1850b6425 100644
--- a/thirdparty/libwebsockets/plat/lws-plat-win.c
+++ b/thirdparty/libwebsockets/plat/lws-plat-win.c
-@@ -635,9 +635,20 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
+@@ -641,9 +641,20 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
HANDLE ret;
WCHAR buf[MAX_PATH];
lws_fop_fd_t fop_fd;
- LARGE_INTEGER llFileSize = {0};
+ FILE_STANDARD_INFO fInfo = {0};
- MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, ARRAY_SIZE(buf));
+ MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, LWS_ARRAY_SIZE(buf));
+
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0602 // Windows 8 (minimum when UWP_ENABLED, but can be used in Windows builds)
+ CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
@@ -24,7 +24,7 @@ index 948db6289..511e29739 100644
if (((*flags) & 7) == _O_RDONLY) {
ret = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-@@ -645,6 +656,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
+@@ -651,6 +662,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
ret = CreateFileW(buf, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
@@ -32,7 +32,7 @@ index 948db6289..511e29739 100644
if (ret == LWS_INVALID_FILE)
goto bail;
-@@ -657,9 +669,9 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
+@@ -663,9 +675,9 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
fop_fd->fd = ret;
fop_fd->filesystem_priv = NULL; /* we don't use it */
fop_fd->flags = *flags;
diff --git a/thirdparty/libwebsockets/win32helpers/getopt.c b/thirdparty/libwebsockets/win32helpers/getopt.c
index 2181f1cb12..3bb21f6f28 100644
--- a/thirdparty/libwebsockets/win32helpers/getopt.c
+++ b/thirdparty/libwebsockets/win32helpers/getopt.c
@@ -1,153 +1,153 @@
-/* $NetBSD: getopt.c,v 1.16 1999/12/02 13:15:56 kleink Exp $ */
-
-/*
- * Copyright (c) 1987, 1993, 1994
- * The Regents of the University of California. 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
- */
-
-#if 0
-static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
-#endif
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#define __P(x) x
-#define _DIAGASSERT(x) assert(x)
-
-#ifdef __weak_alias
-__weak_alias(getopt,_getopt);
-#endif
-
-
-int opterr = 1, /* if error message should be printed */
- optind = 1, /* index into parent argv vector */
- optopt, /* character checked for validity */
- optreset; /* reset getopt */
-char *optarg; /* argument associated with option */
-
-static char * _progname __P((char *));
-int getopt_internal __P((int, char * const *, const char *));
-
-static char *
-_progname(nargv0)
- char * nargv0;
-{
- char * tmp;
-
- _DIAGASSERT(nargv0 != NULL);
-
- tmp = strrchr(nargv0, '/');
- if (tmp)
- tmp++;
- else
- tmp = nargv0;
- return(tmp);
-}
-
-#define BADCH (int)'?'
-#define BADARG (int)':'
-#define EMSG ""
-
-/*
- * getopt --
- * Parse argc/argv argument vector.
- */
-int
-getopt(nargc, nargv, ostr)
- int nargc;
- char * const nargv[];
- const char *ostr;
-{
- static char *__progname = 0;
- static char *place = EMSG; /* option letter processing */
- char *oli; /* option letter list index */
- __progname = __progname?__progname:_progname(*nargv);
-
- _DIAGASSERT(nargv != NULL);
- _DIAGASSERT(ostr != NULL);
-
- if (optreset || !*place) { /* update scanning pointer */
- optreset = 0;
- if (optind >= nargc || *(place = nargv[optind]) != '-') {
- place = EMSG;
- return (-1);
- }
- if (place[1] && *++place == '-' /* found "--" */
- && place[1] == '\0') {
- ++optind;
- place = EMSG;
- return (-1);
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' ||
- !(oli = strchr(ostr, optopt))) {
- /*
- * if the user didn't specify '-' as an option,
- * assume it means -1.
- */
- if (optopt == (int)'-')
- return (-1);
- if (!*place)
- ++optind;
- if (opterr && *ostr != ':')
- (void)fprintf(stderr,
- "%s: illegal option -- %c\n", __progname, optopt);
- return (BADCH);
- }
- if (*++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place)
- ++optind;
- }
- else { /* need an argument */
- if (*place) /* no white space */
- optarg = place;
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- if (*ostr == ':')
- return (BADARG);
- if (opterr)
- (void)fprintf(stderr,
- "%s: option requires an argument -- %c\n",
- __progname, optopt);
- return (BADCH);
- }
- else /* white space */
- optarg = nargv[optind];
- place = EMSG;
- ++optind;
- }
- return (optopt); /* dump back option letter */
-}
-
+/* $NetBSD: getopt.c,v 1.16 1999/12/02 13:15:56 kleink Exp $ */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#if 0
+static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#define __P(x) x
+#define _DIAGASSERT(x) assert(x)
+
+#ifdef __weak_alias
+__weak_alias(getopt,_getopt);
+#endif
+
+
+int opterr = 1, /* if error message should be printed */
+ optind = 1, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+
+static char * _progname __P((char *));
+int getopt_internal __P((int, char * const *, const char *));
+
+static char *
+_progname(nargv0)
+ char * nargv0;
+{
+ char * tmp;
+
+ _DIAGASSERT(nargv0 != NULL);
+
+ tmp = strrchr(nargv0, '/');
+ if (tmp)
+ tmp++;
+ else
+ tmp = nargv0;
+ return(tmp);
+}
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt(nargc, nargv, ostr)
+ int nargc;
+ char * const nargv[];
+ const char *ostr;
+{
+ static char *__progname = 0;
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+ __progname = __progname?__progname:_progname(*nargv);
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(ostr != NULL);
+
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return (-1);
+ }
+ if (place[1] && *++place == '-' /* found "--" */
+ && place[1] == '\0') {
+ ++optind;
+ place = EMSG;
+ return (-1);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means -1.
+ */
+ if (optopt == (int)'-')
+ return (-1);
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':')
+ (void)fprintf(stderr,
+ "%s: illegal option -- %c\n", __progname, optopt);
+ return (BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return (BADARG);
+ if (opterr)
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ __progname, optopt);
+ return (BADCH);
+ }
+ else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return (optopt); /* dump back option letter */
+}
+
diff --git a/thirdparty/libwebsockets/win32helpers/getopt_long.c b/thirdparty/libwebsockets/win32helpers/getopt_long.c
index 22e5fa8945..6dfccf367d 100644
--- a/thirdparty/libwebsockets/win32helpers/getopt_long.c
+++ b/thirdparty/libwebsockets/win32helpers/getopt_long.c
@@ -1,240 +1,240 @@
-
-/*
- * Copyright (c) 1987, 1993, 1994, 1996
- * The Regents of the University of California. 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
- */
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "getopt.h"
-
-#define lws_ptr_diff(head, tail) \
- ((int)((char *)(head) - (char *)(tail)))
-
-extern int opterr; /* if error message should be printed */
-extern int optind; /* index into parent argv vector */
-extern int optopt; /* character checked for validity */
-extern int optreset; /* reset getopt */
-extern char *optarg; /* argument associated with option */
-
-#define __P(x) x
-#define _DIAGASSERT(x) assert(x)
-
-static char * __progname __P((char *));
-int getopt_internal __P((int, char * const *, const char *));
-
-static char *
-__progname(nargv0)
- char * nargv0;
-{
- char * tmp;
-
- _DIAGASSERT(nargv0 != NULL);
-
- tmp = strrchr(nargv0, '/');
- if (tmp)
- tmp++;
- else
- tmp = nargv0;
- return(tmp);
-}
-
-#define BADCH (int)'?'
-#define BADARG (int)':'
-#define EMSG ""
-
-/*
- * getopt --
- * Parse argc/argv argument vector.
- */
-int
-getopt_internal(nargc, nargv, ostr)
- int nargc;
- char * const *nargv;
- const char *ostr;
-{
- static char *place = EMSG; /* option letter processing */
- char *oli; /* option letter list index */
-
- _DIAGASSERT(nargv != NULL);
- _DIAGASSERT(ostr != NULL);
-
- if (optreset || !*place) { /* update scanning pointer */
- optreset = 0;
- if (optind >= nargc || *(place = nargv[optind]) != '-') {
- place = EMSG;
- return (-1);
- }
- if (place[1] && *++place == '-') { /* found "--" */
- /* ++optind; */
- place = EMSG;
- return (-2);
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' ||
- !(oli = strchr(ostr, optopt))) {
- /*
- * if the user didn't specify '-' as an option,
- * assume it means -1.
- */
- if (optopt == (int)'-')
- return (-1);
- if (!*place)
- ++optind;
- if (opterr && *ostr != ':')
- (void)fprintf(stderr,
- "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
- return (BADCH);
- }
- if (*++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place)
- ++optind;
- } else { /* need an argument */
- if (*place) /* no white space */
- optarg = place;
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- if ((opterr) && (*ostr != ':'))
- (void)fprintf(stderr,
- "%s: option requires an argument -- %c\n",
- __progname(nargv[0]), optopt);
- return (BADARG);
- } else /* white space */
- optarg = nargv[optind];
- place = EMSG;
- ++optind;
- }
- return (optopt); /* dump back option letter */
-}
-
-#if 0
-/*
- * getopt --
- * Parse argc/argv argument vector.
- */
-int
-getopt2(nargc, nargv, ostr)
- int nargc;
- char * const *nargv;
- const char *ostr;
-{
- int retval;
-
- if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
- retval = -1;
- ++optind;
- }
- return(retval);
-}
-#endif
-
-/*
- * getopt_long --
- * Parse argc/argv argument vector.
- */
-int
-getopt_long(nargc, nargv, options, long_options, index)
- int nargc;
- char ** nargv;
- char * options;
- struct option * long_options;
- int * index;
-{
- int retval;
-
- _DIAGASSERT(nargv != NULL);
- _DIAGASSERT(options != NULL);
- _DIAGASSERT(long_options != NULL);
- /* index may be NULL */
-
- if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
- char *current_argv = nargv[optind++] + 2, *has_equal;
- int i, current_argv_len, match = -1;
-
- if (*current_argv == '\0') {
- return(-1);
- }
- if ((has_equal = strchr(current_argv, '=')) != NULL) {
- current_argv_len = lws_ptr_diff(has_equal, current_argv);
- has_equal++;
- } else
- current_argv_len = (int)strlen(current_argv);
-
- for (i = 0; long_options[i].name; i++) {
- if (strncmp(current_argv, long_options[i].name, current_argv_len))
- continue;
-
- if (strlen(long_options[i].name) == (unsigned)current_argv_len) {
- match = i;
- break;
- }
- if (match == -1)
- match = i;
- }
- if (match != -1) {
- if (long_options[match].has_arg == required_argument ||
- long_options[match].has_arg == optional_argument) {
- if (has_equal)
- optarg = has_equal;
- else
- optarg = nargv[optind++];
- }
- if ((long_options[match].has_arg == required_argument)
- && (optarg == NULL)) {
- /*
- * Missing argument, leading :
- * indicates no error should be generated
- */
- if ((opterr) && (*options != ':'))
- (void)fprintf(stderr,
- "%s: option requires an argument -- %s\n",
- __progname(nargv[0]), current_argv);
- return (BADARG);
- }
- } else { /* No matching argument */
- if ((opterr) && (*options != ':'))
- (void)fprintf(stderr,
- "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
- return (BADCH);
- }
- if (long_options[match].flag) {
- *long_options[match].flag = long_options[match].val;
- retval = 0;
- } else
- retval = long_options[match].val;
- if (index)
- *index = match;
- }
- return(retval);
-}
+
+/*
+ * Copyright (c) 1987, 1993, 1994, 1996
+ * The Regents of the University of California. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+
+#define lws_ptr_diff(head, tail) \
+ ((int)((char *)(head) - (char *)(tail)))
+
+extern int opterr; /* if error message should be printed */
+extern int optind; /* index into parent argv vector */
+extern int optopt; /* character checked for validity */
+extern int optreset; /* reset getopt */
+extern char *optarg; /* argument associated with option */
+
+#define __P(x) x
+#define _DIAGASSERT(x) assert(x)
+
+static char * __progname __P((char *));
+int getopt_internal __P((int, char * const *, const char *));
+
+static char *
+__progname(nargv0)
+ char * nargv0;
+{
+ char * tmp;
+
+ _DIAGASSERT(nargv0 != NULL);
+
+ tmp = strrchr(nargv0, '/');
+ if (tmp)
+ tmp++;
+ else
+ tmp = nargv0;
+ return(tmp);
+}
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt_internal(nargc, nargv, ostr)
+ int nargc;
+ char * const *nargv;
+ const char *ostr;
+{
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(ostr != NULL);
+
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return (-1);
+ }
+ if (place[1] && *++place == '-') { /* found "--" */
+ /* ++optind; */
+ place = EMSG;
+ return (-2);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means -1.
+ */
+ if (optopt == (int)'-')
+ return (-1);
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':')
+ (void)fprintf(stderr,
+ "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
+ return (BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ } else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if ((opterr) && (*ostr != ':'))
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ __progname(nargv[0]), optopt);
+ return (BADARG);
+ } else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return (optopt); /* dump back option letter */
+}
+
+#if 0
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt2(nargc, nargv, ostr)
+ int nargc;
+ char * const *nargv;
+ const char *ostr;
+{
+ int retval;
+
+ if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
+ retval = -1;
+ ++optind;
+ }
+ return(retval);
+}
+#endif
+
+/*
+ * getopt_long --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt_long(nargc, nargv, options, long_options, index)
+ int nargc;
+ char ** nargv;
+ char * options;
+ struct option * long_options;
+ int * index;
+{
+ int retval;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+ _DIAGASSERT(long_options != NULL);
+ /* index may be NULL */
+
+ if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+ char *current_argv = nargv[optind++] + 2, *has_equal;
+ int i, current_argv_len, match = -1;
+
+ if (*current_argv == '\0') {
+ return(-1);
+ }
+ if ((has_equal = strchr(current_argv, '=')) != NULL) {
+ current_argv_len = lws_ptr_diff(has_equal, current_argv);
+ has_equal++;
+ } else
+ current_argv_len = (int)strlen(current_argv);
+
+ for (i = 0; long_options[i].name; i++) {
+ if (strncmp(current_argv, long_options[i].name, current_argv_len))
+ continue;
+
+ if (strlen(long_options[i].name) == (unsigned)current_argv_len) {
+ match = i;
+ break;
+ }
+ if (match == -1)
+ match = i;
+ }
+ if (match != -1) {
+ if (long_options[match].has_arg == required_argument ||
+ long_options[match].has_arg == optional_argument) {
+ if (has_equal)
+ optarg = has_equal;
+ else
+ optarg = nargv[optind++];
+ }
+ if ((long_options[match].has_arg == required_argument)
+ && (optarg == NULL)) {
+ /*
+ * Missing argument, leading :
+ * indicates no error should be generated
+ */
+ if ((opterr) && (*options != ':'))
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %s\n",
+ __progname(nargv[0]), current_argv);
+ return (BADARG);
+ }
+ } else { /* No matching argument */
+ if ((opterr) && (*options != ':'))
+ (void)fprintf(stderr,
+ "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
+ return (BADCH);
+ }
+ if (long_options[match].flag) {
+ *long_options[match].flag = long_options[match].val;
+ retval = 0;
+ } else
+ retval = long_options[match].val;
+ if (index)
+ *index = match;
+ }
+ return(retval);
+}
diff --git a/thirdparty/libwebsockets/win32helpers/gettimeofday.c b/thirdparty/libwebsockets/win32helpers/gettimeofday.c
index 08385c2320..35dd73531d 100644
--- a/thirdparty/libwebsockets/win32helpers/gettimeofday.c
+++ b/thirdparty/libwebsockets/win32helpers/gettimeofday.c
@@ -1,36 +1,36 @@
-#include <time.h>
-#include <windows.h> //I've omitted context line
-
-#include "gettimeofday.h"
-
-int gettimeofday(struct timeval *tv, struct timezone *tz)
-{
- FILETIME ft;
- unsigned __int64 tmpres = 0;
- static int tzflag;
-
- if (NULL != tv) {
- GetSystemTimeAsFileTime(&ft);
-
- tmpres |= ft.dwHighDateTime;
- tmpres <<= 32;
- tmpres |= ft.dwLowDateTime;
-
- /*converting file time to unix epoch*/
- tmpres /= 10; /*convert into microseconds*/
+#include <time.h>
+#include <windows.h> //I've omitted context line
+
+#include "gettimeofday.h"
+
+int gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ FILETIME ft;
+ unsigned __int64 tmpres = 0;
+ static int tzflag;
+
+ if (NULL != tv) {
+ GetSystemTimeAsFileTime(&ft);
+
+ tmpres |= ft.dwHighDateTime;
+ tmpres <<= 32;
+ tmpres |= ft.dwLowDateTime;
+
+ /*converting file time to unix epoch*/
+ tmpres /= 10; /*convert into microseconds*/
tmpres -= DELTA_EPOCH_IN_MICROSECS;
- tv->tv_sec = (long)(tmpres / 1000000UL);
- tv->tv_usec = (long)(tmpres % 1000000UL);
- }
-
- if (NULL != tz) {
- if (!tzflag) {
- _tzset();
- tzflag++;
- }
- tz->tz_minuteswest = _timezone / 60;
- tz->tz_dsttime = _daylight;
- }
-
- return 0;
-}
+ tv->tv_sec = (long)(tmpres / 1000000UL);
+ tv->tv_usec = (long)(tmpres % 1000000UL);
+ }
+
+ if (NULL != tz) {
+ if (!tzflag) {
+ _tzset();
+ tzflag++;
+ }
+ tz->tz_minuteswest = _timezone / 60;
+ tz->tz_dsttime = _daylight;
+ }
+
+ return 0;
+}
diff --git a/thirdparty/misc/ifaddrs-android.cc b/thirdparty/misc/ifaddrs-android.cc
new file mode 100644
index 0000000000..1f8835b829
--- /dev/null
+++ b/thirdparty/misc/ifaddrs-android.cc
@@ -0,0 +1,221 @@
+/*
+ * libjingle
+ * Copyright 2012, Google Inc.
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#include "ifaddrs-android.h"
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <errno.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+struct netlinkrequest {
+ nlmsghdr header;
+ ifaddrmsg msg;
+};
+namespace {
+const int kMaxReadSize = 4096;
+};
+int set_ifname(struct ifaddrs* ifaddr, int interface) {
+ char buf[IFNAMSIZ] = {0};
+ char* name = if_indextoname(interface, buf);
+ if (name == NULL) {
+ return -1;
+ }
+ ifaddr->ifa_name = new char[strlen(name) + 1];
+ strncpy(ifaddr->ifa_name, name, strlen(name) + 1);
+ return 0;
+}
+int set_flags(struct ifaddrs* ifaddr) {
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd == -1) {
+ return -1;
+ }
+ ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ - 1);
+ int rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
+ close(fd);
+ if (rc == -1) {
+ return -1;
+ }
+ ifaddr->ifa_flags = ifr.ifr_flags;
+ return 0;
+}
+int set_addresses(struct ifaddrs* ifaddr, ifaddrmsg* msg, void* data,
+ size_t len) {
+ if (msg->ifa_family == AF_INET) {
+ sockaddr_in* sa = new sockaddr_in;
+ sa->sin_family = AF_INET;
+ memcpy(&sa->sin_addr, data, len);
+ ifaddr->ifa_addr = reinterpret_cast<sockaddr*>(sa);
+ } else if (msg->ifa_family == AF_INET6) {
+ sockaddr_in6* sa = new sockaddr_in6;
+ sa->sin6_family = AF_INET6;
+ sa->sin6_scope_id = msg->ifa_index;
+ memcpy(&sa->sin6_addr, data, len);
+ ifaddr->ifa_addr = reinterpret_cast<sockaddr*>(sa);
+ } else {
+ return -1;
+ }
+ return 0;
+}
+int make_prefixes(struct ifaddrs* ifaddr, int family, int prefixlen) {
+ char* prefix = NULL;
+ if (family == AF_INET) {
+ sockaddr_in* mask = new sockaddr_in;
+ mask->sin_family = AF_INET;
+ memset(&mask->sin_addr, 0, sizeof(in_addr));
+ ifaddr->ifa_netmask = reinterpret_cast<sockaddr*>(mask);
+ if (prefixlen > 32) {
+ prefixlen = 32;
+ }
+ prefix = reinterpret_cast<char*>(&mask->sin_addr);
+ } else if (family == AF_INET6) {
+ sockaddr_in6* mask = new sockaddr_in6;
+ mask->sin6_family = AF_INET6;
+ memset(&mask->sin6_addr, 0, sizeof(in6_addr));
+ ifaddr->ifa_netmask = reinterpret_cast<sockaddr*>(mask);
+ if (prefixlen > 128) {
+ prefixlen = 128;
+ }
+ prefix = reinterpret_cast<char*>(&mask->sin6_addr);
+ } else {
+ return -1;
+ }
+ for (int i = 0; i < (prefixlen / 8); i++) {
+ *prefix++ = 0xFF;
+ }
+ char remainder = 0xff;
+ remainder <<= (8 - prefixlen % 8);
+ *prefix = remainder;
+ return 0;
+}
+int populate_ifaddrs(struct ifaddrs* ifaddr, ifaddrmsg* msg, void* bytes,
+ size_t len) {
+ if (set_ifname(ifaddr, msg->ifa_index) != 0) {
+ return -1;
+ }
+ if (set_flags(ifaddr) != 0) {
+ return -1;
+ }
+ if (set_addresses(ifaddr, msg, bytes, len) != 0) {
+ return -1;
+ }
+ if (make_prefixes(ifaddr, msg->ifa_family, msg->ifa_prefixlen) != 0) {
+ return -1;
+ }
+ return 0;
+}
+int getifaddrs(struct ifaddrs** result) {
+ int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (fd < 0) {
+ return -1;
+ }
+ netlinkrequest ifaddr_request;
+ memset(&ifaddr_request, 0, sizeof(ifaddr_request));
+ ifaddr_request.header.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
+ ifaddr_request.header.nlmsg_type = RTM_GETADDR;
+ ifaddr_request.header.nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrmsg));
+ ssize_t count = send(fd, &ifaddr_request, ifaddr_request.header.nlmsg_len, 0);
+ if (static_cast<size_t>(count) != ifaddr_request.header.nlmsg_len) {
+ close(fd);
+ return -1;
+ }
+ struct ifaddrs* start = NULL;
+ struct ifaddrs* current = NULL;
+ char buf[kMaxReadSize];
+ ssize_t amount_read = recv(fd, &buf, kMaxReadSize, 0);
+ while (amount_read > 0) {
+ nlmsghdr* header = reinterpret_cast<nlmsghdr*>(&buf[0]);
+ size_t header_size = static_cast<size_t>(amount_read);
+ for ( ; NLMSG_OK(header, header_size);
+ header = NLMSG_NEXT(header, header_size)) {
+ switch (header->nlmsg_type) {
+ case NLMSG_DONE:
+ // Success. Return.
+ *result = start;
+ close(fd);
+ return 0;
+ case NLMSG_ERROR:
+ close(fd);
+ freeifaddrs(start);
+ return -1;
+ case RTM_NEWADDR: {
+ ifaddrmsg* address_msg =
+ reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(header));
+ rtattr* rta = IFA_RTA(address_msg);
+ ssize_t payload_len = IFA_PAYLOAD(header);
+ while (RTA_OK(rta, payload_len)) {
+ if (rta->rta_type == IFA_ADDRESS) {
+ int family = address_msg->ifa_family;
+ if (family == AF_INET || family == AF_INET6) {
+ ifaddrs* newest = new ifaddrs;
+ memset(newest, 0, sizeof(ifaddrs));
+ if (current) {
+ current->ifa_next = newest;
+ } else {
+ start = newest;
+ }
+ if (populate_ifaddrs(newest, address_msg, RTA_DATA(rta),
+ RTA_PAYLOAD(rta)) != 0) {
+ freeifaddrs(start);
+ *result = NULL;
+ return -1;
+ }
+ current = newest;
+ }
+ }
+ rta = RTA_NEXT(rta, payload_len);
+ }
+ break;
+ }
+ }
+ }
+ amount_read = recv(fd, &buf, kMaxReadSize, 0);
+ }
+ close(fd);
+ freeifaddrs(start);
+ return -1;
+}
+void freeifaddrs(struct ifaddrs* addrs) {
+ struct ifaddrs* last = NULL;
+ struct ifaddrs* cursor = addrs;
+ while (cursor) {
+ delete[] cursor->ifa_name;
+ delete cursor->ifa_addr;
+ delete cursor->ifa_netmask;
+ last = cursor;
+ cursor = cursor->ifa_next;
+ delete last;
+ }
+}
diff --git a/thirdparty/misc/ifaddrs-android.h b/thirdparty/misc/ifaddrs-android.h
new file mode 100644
index 0000000000..6e204af26f
--- /dev/null
+++ b/thirdparty/misc/ifaddrs-android.h
@@ -0,0 +1,46 @@
+/*
+ * libjingle
+ * Copyright 2013, Google Inc.
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+#ifndef TALK_BASE_IFADDRS_ANDROID_H_
+#define TALK_BASE_IFADDRS_ANDROID_H_
+#include <stdio.h>
+#include <sys/socket.h>
+// Implementation of getifaddrs for Android.
+// Fills out a list of ifaddr structs (see below) which contain information
+// about every network interface available on the host.
+// See 'man getifaddrs' on Linux or OS X (nb: it is not a POSIX function).
+struct ifaddrs {
+ struct ifaddrs* ifa_next;
+ char* ifa_name;
+ unsigned int ifa_flags;
+ struct sockaddr* ifa_addr;
+ struct sockaddr* ifa_netmask;
+ // Real ifaddrs has broadcast, point to point and data members.
+ // We don't need them (yet?).
+};
+int getifaddrs(struct ifaddrs** result);
+void freeifaddrs(struct ifaddrs* addrs);
+#endif // TALK_BASE_IFADDRS_ANDROID_H_
diff --git a/thirdparty/squish/Add-Decompress-Bc5-to-Squish.patch b/thirdparty/squish/Add-Decompress-Bc5-to-Squish.patch
deleted file mode 100644
index 1e06a8d318..0000000000
--- a/thirdparty/squish/Add-Decompress-Bc5-to-Squish.patch
+++ /dev/null
@@ -1,143 +0,0 @@
-From 7b64cc4c8b0be0443741483bf65909f5140179c0 Mon Sep 17 00:00:00 2001
-From: Orkun <orkuntezerm@gmail.com>
-Date: Sun, 19 Nov 2017 02:24:31 +0300
-Subject: [PATCH] Fix #12220: Add Decompress Bc5 to Squish
-
-This Commit fixes the corrupted file preview described in #12220.
-Added DecompressColourBc5 function to squish.
----
- thirdparty/squish/colourblock.cpp | 85 +++++++++++++++++++++++++++++++++++++++
- thirdparty/squish/colourblock.h | 3 ++
- thirdparty/squish/squish.cpp | 8 +++-
- 3 files changed, 95 insertions(+), 1 deletion(-)
-
-diff --git a/thirdparty/squish/colourblock.cpp b/thirdparty/squish/colourblock.cpp
-index af8b98036..3de46382c 100644
---- a/thirdparty/squish/colourblock.cpp
-+++ b/thirdparty/squish/colourblock.cpp
-@@ -211,4 +211,89 @@ void DecompressColour( u8* rgba, void const* block, bool isDxt1 )
- }
- }
-
-+// -- Godot start --
-+void DecompressColourBc5( u8* rgba, void const* block)
-+{
-+ // get the block bytes
-+ u8 const* bytes = reinterpret_cast< u8 const* >( block );
-+
-+ // unpack the endpoints
-+ u8 codes[16];
-+ int red_0 = bytes[0];
-+ int red_1 = bytes[1];
-+
-+ codes[0] = red_0;
-+ codes[1] = red_1;
-+ codes[6] = 0.0f;
-+ codes[7] = 1.0f;
-+ // generate the midpoints
-+ if(red_0 > red_1)
-+ {
-+ for( int i = 2; i < 8; ++i )
-+ {
-+ codes[i] = ((8-i)*red_0 + (i-1)*red_1)/7;
-+ }
-+ }
-+ else
-+ {
-+ for( int i = 2; i < 6; ++i )
-+ {
-+ codes[i] = ((6-i)*red_0 + (i-1)*red_1)/5;
-+ }
-+ }
-+
-+ int green_0 = bytes[8];
-+ int green_1 = bytes[9];
-+
-+ codes[0 + 8] = green_0;
-+ codes[1 + 8] = green_1;
-+ codes[6 + 8] = 0.0f;
-+ codes[7 + 8] = 1.0f;
-+ // generate the midpoints
-+ if(green_0 > green_1)
-+ {
-+ for( int i = 2; i < 8; ++i )
-+ {
-+ codes[i + 8] = ((8-i)*green_0 + (i-1)*green_1)/7;
-+ }
-+ }
-+ else
-+ {
-+ for( int i = 2; i < 6; ++i )
-+ {
-+ codes[i + 8] = ((6-i)*green_0 + (i-1)*green_1)/5;
-+ }
-+ }
-+
-+ u8 indices[32];
-+ for( int i = 0; i < 4; ++i )
-+ {
-+ u8 packed = bytes[2 + i];
-+ u8* red_ind = indices + 4*i;
-+
-+ red_ind[0] = packed & 0x3;
-+ red_ind[1] = ( packed >> 2 ) & 0x3;
-+ red_ind[2] = ( packed >> 4 ) & 0x3;
-+ red_ind[3] = ( packed >> 6 ) & 0x3;
-+
-+ packed = bytes[8 + i];
-+ u8* green_ind = indices + 4*i + 16;
-+ green_ind[0] = packed & 0x3;
-+ green_ind[1] = ( packed >> 2 ) & 0x3;
-+ green_ind[2] = ( packed >> 4 ) & 0x3;
-+ green_ind[3] = ( packed >> 6 ) & 0x3;
-+ }
-+
-+ // store out the colours
-+ for( int i = 0; i < 16; ++i )
-+ {
-+ rgba[4*i] = codes[indices[i]];
-+ rgba[4*i +1] = codes[indices[i + 16] + 8];
-+ rgba[4*i +2] = 0;
-+ rgba[4*i +3] = 255;
-+ }
-+}
-+// -- GODOT end --
-+
-+
- } // namespace squish
-diff --git a/thirdparty/squish/colourblock.h b/thirdparty/squish/colourblock.h
-index fee2cd7c5..3cb9b7e3b 100644
---- a/thirdparty/squish/colourblock.h
-+++ b/thirdparty/squish/colourblock.h
-@@ -35,6 +35,9 @@ void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void*
- void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block );
-
- void DecompressColour( u8* rgba, void const* block, bool isDxt1 );
-+// -- GODOT start --
-+void DecompressColourBc5( u8* rgba, void const* block );
-+// -- GODOT end --
-
- } // namespace squish
-
-diff --git a/thirdparty/squish/squish.cpp b/thirdparty/squish/squish.cpp
-index 1d22a64ad..fd11a147d 100644
---- a/thirdparty/squish/squish.cpp
-+++ b/thirdparty/squish/squish.cpp
-@@ -135,7 +135,13 @@ void Decompress( u8* rgba, void const* block, int flags )
- colourBlock = reinterpret_cast< u8 const* >( block ) + 8;
-
- // decompress colour
-- DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 );
-+ // -- GODOT start --
-+ //DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 );
-+ if(( flags & ( kBc5 ) ) != 0)
-+ DecompressColourBc5( rgba, colourBlock);
-+ else
-+ DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 );
-+ // -- GODOT end --
-
- // decompress alpha separately if necessary
- if( ( flags & kDxt3 ) != 0 )
---
-2.13.6
-
diff --git a/thirdparty/squish/colourblock.cpp b/thirdparty/squish/colourblock.cpp
index 3de46382c0..3d87adaa77 100644
--- a/thirdparty/squish/colourblock.cpp
+++ b/thirdparty/squish/colourblock.cpp
@@ -24,6 +24,9 @@
-------------------------------------------------------------------------- */
#include "colourblock.h"
+// -- Godot start --
+#include "alpha.h"
+// -- Godot end --
namespace squish {
@@ -214,83 +217,17 @@ void DecompressColour( u8* rgba, void const* block, bool isDxt1 )
// -- Godot start --
void DecompressColourBc5( u8* rgba, void const* block)
{
- // get the block bytes
- u8 const* bytes = reinterpret_cast< u8 const* >( block );
-
- // unpack the endpoints
- u8 codes[16];
- int red_0 = bytes[0];
- int red_1 = bytes[1];
-
- codes[0] = red_0;
- codes[1] = red_1;
- codes[6] = 0.0f;
- codes[7] = 1.0f;
- // generate the midpoints
- if(red_0 > red_1)
- {
- for( int i = 2; i < 8; ++i )
- {
- codes[i] = ((8-i)*red_0 + (i-1)*red_1)/7;
- }
- }
- else
- {
- for( int i = 2; i < 6; ++i )
- {
- codes[i] = ((6-i)*red_0 + (i-1)*red_1)/5;
- }
- }
-
- int green_0 = bytes[8];
- int green_1 = bytes[9];
-
- codes[0 + 8] = green_0;
- codes[1 + 8] = green_1;
- codes[6 + 8] = 0.0f;
- codes[7 + 8] = 1.0f;
- // generate the midpoints
- if(green_0 > green_1)
- {
- for( int i = 2; i < 8; ++i )
- {
- codes[i + 8] = ((8-i)*green_0 + (i-1)*green_1)/7;
- }
- }
- else
- {
- for( int i = 2; i < 6; ++i )
- {
- codes[i + 8] = ((6-i)*green_0 + (i-1)*green_1)/5;
- }
- }
-
- u8 indices[32];
- for( int i = 0; i < 4; ++i )
- {
- u8 packed = bytes[2 + i];
- u8* red_ind = indices + 4*i;
-
- red_ind[0] = packed & 0x3;
- red_ind[1] = ( packed >> 2 ) & 0x3;
- red_ind[2] = ( packed >> 4 ) & 0x3;
- red_ind[3] = ( packed >> 6 ) & 0x3;
-
- packed = bytes[8 + i];
- u8* green_ind = indices + 4*i + 16;
- green_ind[0] = packed & 0x3;
- green_ind[1] = ( packed >> 2 ) & 0x3;
- green_ind[2] = ( packed >> 4 ) & 0x3;
- green_ind[3] = ( packed >> 6 ) & 0x3;
+ void const* rblock = block;
+ void const* gblock = reinterpret_cast< u8 const* >( block ) + 8;
+ DecompressAlphaDxt5(rgba,rblock);
+ for ( int i = 0; i < 16; ++i ) {
+ rgba[i*4] = rgba[i*4 + 3];
}
-
- // store out the colours
- for( int i = 0; i < 16; ++i )
- {
- rgba[4*i] = codes[indices[i]];
- rgba[4*i +1] = codes[indices[i + 16] + 8];
- rgba[4*i +2] = 0;
- rgba[4*i +3] = 255;
+ DecompressAlphaDxt5(rgba,gblock);
+ for ( int i = 0; i < 16; ++i ) {
+ rgba[i*4+1] = rgba[i*4 + 3];
+ rgba[i*4 + 2] = 0;
+ rgba[i*4 + 3] = 255;
}
}
// -- GODOT end --
diff --git a/thirdparty/squish/godot-changes.patch b/thirdparty/squish/godot-changes.patch
new file mode 100644
index 0000000000..ef7bafb4b4
--- /dev/null
+++ b/thirdparty/squish/godot-changes.patch
@@ -0,0 +1,102 @@
+diff --git a/thirdparty/squish/colourblock.cpp b/thirdparty/squish/colourblock.cpp
+index af8b98036..3d87adaa7 100644
+--- a/thirdparty/squish/colourblock.cpp
++++ b/thirdparty/squish/colourblock.cpp
+@@ -24,6 +24,9 @@
+ -------------------------------------------------------------------------- */
+
+ #include "colourblock.h"
++// -- Godot start --
++#include "alpha.h"
++// -- Godot end --
+
+ namespace squish {
+
+@@ -211,4 +214,23 @@ void DecompressColour( u8* rgba, void const* block, bool isDxt1 )
+ }
+ }
+
++// -- Godot start --
++void DecompressColourBc5( u8* rgba, void const* block)
++{
++ void const* rblock = block;
++ void const* gblock = reinterpret_cast< u8 const* >( block ) + 8;
++ DecompressAlphaDxt5(rgba,rblock);
++ for ( int i = 0; i < 16; ++i ) {
++ rgba[i*4] = rgba[i*4 + 3];
++ }
++ DecompressAlphaDxt5(rgba,gblock);
++ for ( int i = 0; i < 16; ++i ) {
++ rgba[i*4+1] = rgba[i*4 + 3];
++ rgba[i*4 + 2] = 0;
++ rgba[i*4 + 3] = 255;
++ }
++}
++// -- GODOT end --
++
++
+ } // namespace squish
+diff --git a/thirdparty/squish/colourblock.h b/thirdparty/squish/colourblock.h
+index fee2cd7c5..3cb9b7e3b 100644
+--- a/thirdparty/squish/colourblock.h
++++ b/thirdparty/squish/colourblock.h
+@@ -35,6 +35,9 @@ void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void*
+ void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block );
+
+ void DecompressColour( u8* rgba, void const* block, bool isDxt1 );
++// -- GODOT start --
++void DecompressColourBc5( u8* rgba, void const* block );
++// -- GODOT end --
+
+ } // namespace squish
+
+diff --git a/thirdparty/squish/config.h b/thirdparty/squish/config.h
+index 92edefe96..05f8d7259 100644
+--- a/thirdparty/squish/config.h
++++ b/thirdparty/squish/config.h
+@@ -32,6 +32,26 @@
+ #endif
+
+ // Set to 1 or 2 when building squish to use SSE or SSE2 instructions.
++// -- GODOT start --
++#ifdef _MSC_VER
++ #if defined(_M_IX86_FP)
++ #if _M_IX86_FP >= 2
++ #define SQUISH_USE_SSE 2
++ #elif _M_IX86_FP >= 1
++ #define SQUISH_USE_SSE 1
++ #endif
++ #elif defined(_M_X64)
++ #define SQUISH_USE_SSE 2
++ #endif
++#else
++ #if defined(__SSE2__)
++ #define SQUISH_USE_SSE 2
++ #elif defined(__SSE__)
++ #define SQUISH_USE_SSE 1
++ #endif
++#endif
++// -- GODOT end --
++
+ #ifndef SQUISH_USE_SSE
+ #define SQUISH_USE_SSE 0
+ #endif
+diff --git a/thirdparty/squish/squish.cpp b/thirdparty/squish/squish.cpp
+index 1d22a64ad..fd11a147d 100644
+--- a/thirdparty/squish/squish.cpp
++++ b/thirdparty/squish/squish.cpp
+@@ -135,7 +135,13 @@ void Decompress( u8* rgba, void const* block, int flags )
+ colourBlock = reinterpret_cast< u8 const* >( block ) + 8;
+
+ // decompress colour
+- DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 );
++ // -- GODOT start --
++ //DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 );
++ if(( flags & ( kBc5 ) ) != 0)
++ DecompressColourBc5( rgba, colourBlock);
++ else
++ DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 );
++ // -- GODOT end --
+
+ // decompress alpha separately if necessary
+ if( ( flags & kDxt3 ) != 0 )
diff --git a/thirdparty/tinyexr/tinyexr.h b/thirdparty/tinyexr/tinyexr.h
index 990c8ee142..b3a7ee00c2 100644
--- a/thirdparty/tinyexr/tinyexr.h
+++ b/thirdparty/tinyexr/tinyexr.h
@@ -116,6 +116,8 @@ extern "C" {
#define TINYEXR_ERROR_UNSUPPORTED_FORMAT (-7)
#define TINYEXR_ERROR_INVALID_HEADER (-8)
#define TINYEXR_ERROR_UNSUPPORTED_FEATURE (-9)
+#define TINYEXR_ERROR_CANT_WRITE_FILE (-10)
+#define TINYEXR_ERROR_SERIALZATION_FAILED (-11)
// @note { OpenEXR file format: http://www.openexr.com/openexrfilelayout.pdf }
@@ -279,9 +281,12 @@ extern int LoadEXR(float **out_rgba, int *width, int *height,
// Save image as fp16(HALF) format when `save_as_fp16` is positive non-zero
// value.
// Save image as fp32(FLOAT) format when `save_as_fp16` is 0.
+// Use ZIP compression by default.
+// Returns negative value and may set error string in `err` when there's an
+// error
extern int SaveEXR(const float *data, const int width, const int height,
const int components, const int save_as_fp16,
- const char *filename);
+ const char *filename, const char **err);
// Initialize EXRHeader struct
extern void InitEXRHeader(EXRHeader *exr_header);
@@ -400,9 +405,9 @@ extern int SaveEXRImageToFile(const EXRImage *image,
// Saves multi-channel, single-frame OpenEXR image to a memory.
// Image is compressed using EXRImage.compression value.
-// Return the number of bytes if succes.
-// Returns negative value and may set error string in `err` when there's an
-// error
+// Return the number of bytes if success.
+// Return zero and will set error string in `err` when there's an
+// error.
// When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern size_t SaveEXRImageToMemory(const EXRImage *image,
@@ -524,15 +529,23 @@ namespace miniz {
#if __has_warning("-Wcomma")
#pragma clang diagnostic ignored "-Wcomma"
#endif
+
#if __has_warning("-Wmacro-redefined")
#pragma clang diagnostic ignored "-Wmacro-redefined"
#endif
+
#if __has_warning("-Wcast-qual")
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
+
#if __has_warning("-Wzero-as-null-pointer-constant")
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif
+
+#if __has_warning("-Wtautological-constant-compare")
+#pragma clang diagnostic ignored "-Wtautological-constant-compare"
+#endif
+
#endif
/* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP
@@ -2518,10 +2531,10 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r,
tinfl_status status = TINFL_STATUS_FAILED;
mz_uint32 num_bits, dist, counter, num_extra;
tinfl_bit_buf_t bit_buf;
- const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end =
- pIn_buf_next + *pIn_buf_size;
- mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end =
- pOut_buf_next + *pOut_buf_size;
+ const mz_uint8 *pIn_buf_cur = pIn_buf_next,
+ *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
+ mz_uint8 *pOut_buf_cur = pOut_buf_next,
+ *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
size_t out_buf_size_mask =
(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)
? (size_t)-1
@@ -2938,9 +2951,8 @@ void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
tinfl_status status = tinfl_decompress(
&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size,
(mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL,
- &dst_buf_size,
- (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
- TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
+ &dst_buf_size, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
+ TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) {
MZ_FREE(pBuf);
*pOut_len = 0;
@@ -2993,8 +3005,9 @@ int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
tinfl_status status =
tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs,
&in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
- (flags & ~(TINFL_FLAG_HAS_MORE_INPUT |
- TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
+ (flags &
+ ~(TINFL_FLAG_HAS_MORE_INPUT |
+ TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
in_buf_ofs += in_buf_size;
if ((dst_buf_size) &&
(!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
@@ -3119,9 +3132,7 @@ static const mz_uint8 s_tdefl_large_dist_extra[128] = {
// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted
// values.
-typedef struct {
- mz_uint16 m_key, m_sym_index;
-} tdefl_sym_freq;
+typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms,
tdefl_sym_freq *pSyms0,
tdefl_sym_freq *pSyms1) {
@@ -5265,10 +5276,9 @@ mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
pStat->m_comment_size = n;
- memcpy(pStat->m_comment,
- p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
- MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
- MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
+ memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
+ MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
+ MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
n);
pStat->m_comment[n] = '\0';
@@ -10087,9 +10097,10 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
unsigned short *outLine =
reinterpret_cast<unsigned short *>(out_images[c]);
if (line_order == 0) {
- outLine += (y + v) * x_stride;
+ outLine += (size_t(y) + v) * size_t(x_stride);
} else {
- outLine += (height - 1 - (y + v)) * x_stride;
+ outLine +=
+ (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
}
for (int u = 0; u < width; u++) {
@@ -10105,9 +10116,10 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
} else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
float *outLine = reinterpret_cast<float *>(out_images[c]);
if (line_order == 0) {
- outLine += (y + v) * x_stride;
+ outLine += (size_t(y) + v) * size_t(x_stride);
} else {
- outLine += (height - 1 - (y + v)) * x_stride;
+ outLine +=
+ (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
}
if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
@@ -10140,9 +10152,10 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
float *outLine = reinterpret_cast<float *>(out_images[c]);
if (line_order == 0) {
- outLine += (y + v) * x_stride;
+ outLine += (size_t(y) + v) * size_t(x_stride);
} else {
- outLine += (height - 1 - (y + v)) * x_stride;
+ outLine +=
+ (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
}
if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
@@ -10167,9 +10180,10 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
unsigned int *outLine =
reinterpret_cast<unsigned int *>(out_images[c]);
if (line_order == 0) {
- outLine += (y + v) * x_stride;
+ outLine += (size_t(y) + v) * size_t(x_stride);
} else {
- outLine += (height - 1 - (y + v)) * x_stride;
+ outLine +=
+ (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
}
for (int u = 0; u < width; u++) {
@@ -11133,21 +11147,53 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
}
}
- if ((idxA == 0) && (idxR == -1) && (idxG == -1) && (idxB == -1)) {
- // Alpha channel only.
+ if (exr_header.num_channels == 1) {
+ // Grayscale channel only.
- if (exr_header.tiled) {
- // todo.implement this
- }
(*out_rgba) = reinterpret_cast<float *>(
malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
static_cast<size_t>(exr_image.height)));
- for (int i = 0; i < exr_image.width * exr_image.height; i++) {
- const float val = reinterpret_cast<float **>(exr_image.images)[0][i];
- (*out_rgba)[4 * i + 0] = val;
- (*out_rgba)[4 * i + 1] = val;
- (*out_rgba)[4 * i + 2] = val;
- (*out_rgba)[4 * i + 3] = val;
+
+ if (exr_header.tiled) {
+ // todo.implement this
+
+ for (int it = 0; it < exr_image.num_tiles; it++) {
+ for (int j = 0; j < exr_header.tile_size_y; j++) {
+ for (int i = 0; i < exr_header.tile_size_x; i++) {
+ const int ii =
+ exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
+ const int jj =
+ exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
+ const int idx = ii + jj * exr_image.width;
+
+ // out of region check.
+ if (ii >= exr_image.width) {
+ continue;
+ }
+ if (jj >= exr_image.height) {
+ continue;
+ }
+ const int srcIdx = i + j * exr_header.tile_size_x;
+ unsigned char **src = exr_image.tiles[it].images;
+ (*out_rgba)[4 * idx + 0] =
+ reinterpret_cast<float **>(src)[0][srcIdx];
+ (*out_rgba)[4 * idx + 1] =
+ reinterpret_cast<float **>(src)[0][srcIdx];
+ (*out_rgba)[4 * idx + 2] =
+ reinterpret_cast<float **>(src)[0][srcIdx];
+ (*out_rgba)[4 * idx + 3] =
+ reinterpret_cast<float **>(src)[0][srcIdx];
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < exr_image.width * exr_image.height; i++) {
+ const float val = reinterpret_cast<float **>(exr_image.images)[0][i];
+ (*out_rgba)[4 * i + 0] = val;
+ (*out_rgba)[4 * i + 1] = val;
+ (*out_rgba)[4 * i + 2] = val;
+ (*out_rgba)[4 * i + 3] = val;
+ }
}
} else {
// Assume RGB(A)
@@ -11179,7 +11225,7 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
static_cast<size_t>(exr_image.height)));
if (exr_header.tiled) {
for (int it = 0; it < exr_image.num_tiles; it++) {
- for (int j = 0; j < exr_header.tile_size_y; j++)
+ for (int j = 0; j < exr_header.tile_size_y; j++) {
for (int i = 0; i < exr_header.tile_size_x; i++) {
const int ii =
exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
@@ -11209,6 +11255,7 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
(*out_rgba)[4 * idx + 3] = 1.0;
}
}
+ }
}
} else {
for (int i = 0; i < exr_image.width * exr_image.height; i++) {
@@ -11356,18 +11403,53 @@ int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
static_cast<size_t>(exr_image.height)));
- for (int i = 0; i < exr_image.width * exr_image.height; i++) {
- (*out_rgba)[4 * i + 0] =
- reinterpret_cast<float **>(exr_image.images)[idxR][i];
- (*out_rgba)[4 * i + 1] =
- reinterpret_cast<float **>(exr_image.images)[idxG][i];
- (*out_rgba)[4 * i + 2] =
- reinterpret_cast<float **>(exr_image.images)[idxB][i];
- if (idxA != -1) {
- (*out_rgba)[4 * i + 3] =
- reinterpret_cast<float **>(exr_image.images)[idxA][i];
- } else {
- (*out_rgba)[4 * i + 3] = 1.0;
+ if (exr_header.tiled) {
+ for (int it = 0; it < exr_image.num_tiles; it++) {
+ for (int j = 0; j < exr_header.tile_size_y; j++)
+ for (int i = 0; i < exr_header.tile_size_x; i++) {
+ const int ii =
+ exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
+ const int jj =
+ exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
+ const int idx = ii + jj * exr_image.width;
+
+ // out of region check.
+ if (ii >= exr_image.width) {
+ continue;
+ }
+ if (jj >= exr_image.height) {
+ continue;
+ }
+ const int srcIdx = i + j * exr_header.tile_size_x;
+ unsigned char **src = exr_image.tiles[it].images;
+ (*out_rgba)[4 * idx + 0] =
+ reinterpret_cast<float **>(src)[idxR][srcIdx];
+ (*out_rgba)[4 * idx + 1] =
+ reinterpret_cast<float **>(src)[idxG][srcIdx];
+ (*out_rgba)[4 * idx + 2] =
+ reinterpret_cast<float **>(src)[idxB][srcIdx];
+ if (idxA != -1) {
+ (*out_rgba)[4 * idx + 3] =
+ reinterpret_cast<float **>(src)[idxA][srcIdx];
+ } else {
+ (*out_rgba)[4 * idx + 3] = 1.0;
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < exr_image.width * exr_image.height; i++) {
+ (*out_rgba)[4 * i + 0] =
+ reinterpret_cast<float **>(exr_image.images)[idxR][i];
+ (*out_rgba)[4 * i + 1] =
+ reinterpret_cast<float **>(exr_image.images)[idxG][i];
+ (*out_rgba)[4 * i + 2] =
+ reinterpret_cast<float **>(exr_image.images)[idxB][i];
+ if (idxA != -1) {
+ (*out_rgba)[4 * i + 3] =
+ reinterpret_cast<float **>(exr_image.images)[idxA][i];
+ } else {
+ (*out_rgba)[4 * i + 3] = 1.0;
+ }
}
}
@@ -11452,7 +11534,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
if (exr_image == NULL || memory_out == NULL ||
exr_header->compression_type < 0) {
tinyexr::SetErrorMessage("Invalid argument for SaveEXRImageToMemory", err);
- return 0; // @fixme
+ return 0;
}
#if !TINYEXR_USE_PIZ
@@ -11623,8 +11705,6 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
sizeof(
tinyexr::tinyexr_int64); // sizeof(header) + sizeof(offsetTable)
- std::vector<unsigned char> data;
-
std::vector<std::vector<unsigned char> > data_list(
static_cast<size_t>(num_blocks));
std::vector<size_t> channel_offset_list(
@@ -11863,9 +11943,9 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
} else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
#if TINYEXR_USE_PIZ
unsigned int bufLen =
- 1024 + static_cast<unsigned int>(
- 1.2 * static_cast<unsigned int>(
- buf.size())); // @fixme { compute good bound. }
+ 8192 + static_cast<unsigned int>(
+ 2 * static_cast<unsigned int>(
+ buf.size())); // @fixme { compute good bound. }
std::vector<unsigned char> block(bufLen);
unsigned int outSize = static_cast<unsigned int>(block.size());
@@ -11924,13 +12004,12 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
} // omp parallel
for (size_t i = 0; i < static_cast<size_t>(num_blocks); i++) {
- data.insert(data.end(), data_list[i].begin(), data_list[i].end());
-
offsets[i] = offset;
tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64 *>(&offsets[i]));
offset += data_list[i].size();
}
+ size_t totalSize = static_cast<size_t>(offset);
{
memory.insert(
memory.end(), reinterpret_cast<unsigned char *>(&offsets.at(0)),
@@ -11938,14 +12017,21 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
sizeof(tinyexr::tinyexr_uint64) * static_cast<size_t>(num_blocks));
}
- { memory.insert(memory.end(), data.begin(), data.end()); }
-
- assert(memory.size() > 0);
+ if ( memory.size() == 0 ) {
+ tinyexr::SetErrorMessage("Output memory size is zero", err);
+ return 0;
+ }
- (*memory_out) = static_cast<unsigned char *>(malloc(memory.size()));
+ (*memory_out) = static_cast<unsigned char *>(malloc(totalSize));
memcpy((*memory_out), &memory.at(0), memory.size());
+ unsigned char *memory_ptr = *memory_out + memory.size();
- return memory.size(); // OK
+ for (size_t i = 0; i < static_cast<size_t>(num_blocks); i++) {
+ memcpy(memory_ptr, &data_list[i].at(0), data_list[i].size());
+ memory_ptr += data_list[i].size();
+ }
+
+ return totalSize; // OK
}
int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
@@ -11960,7 +12046,7 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
tinyexr::SetErrorMessage("PIZ compression is not supported in this build",
err);
- return 0;
+ return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
}
#endif
@@ -11968,7 +12054,7 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
tinyexr::SetErrorMessage("ZFP compression is not supported in this build",
err);
- return 0;
+ return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
}
#endif
@@ -11980,19 +12066,28 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
#endif
if (!fp) {
tinyexr::SetErrorMessage("Cannot write a file", err);
- return TINYEXR_ERROR_CANT_OPEN_FILE;
+ return TINYEXR_ERROR_CANT_WRITE_FILE;
}
unsigned char *mem = NULL;
size_t mem_size = SaveEXRImageToMemory(exr_image, exr_header, &mem, err);
+ if (mem_size == 0) {
+ return TINYEXR_ERROR_SERIALZATION_FAILED;
+ }
+ size_t written_size = 0;
if ((mem_size > 0) && mem) {
- fwrite(mem, 1, mem_size, fp);
+ written_size = fwrite(mem, 1, mem_size, fp);
}
free(mem);
fclose(fp);
+ if (written_size != mem_size) {
+ tinyexr::SetErrorMessage("Cannot write a file", err);
+ return TINYEXR_ERROR_CANT_WRITE_FILE;
+ }
+
return TINYEXR_SUCCESS;
}
@@ -12861,20 +12956,27 @@ int LoadEXRMultipartImageFromFile(EXRImage *exr_images,
}
int SaveEXR(const float *data, int width, int height, int components,
- const int save_as_fp16, const char *outfilename) {
+ const int save_as_fp16, const char *outfilename, const char **err) {
if ((components == 1) || components == 3 || components == 4) {
// OK
} else {
+ std::stringstream ss;
+ ss << "Unsupported component value : " << components << std::endl;
+
+ tinyexr::SetErrorMessage(ss.str(), err);
return TINYEXR_ERROR_INVALID_ARGUMENT;
}
- // Assume at least 16x16 pixels.
- if (width < 16) return TINYEXR_ERROR_INVALID_ARGUMENT;
- if (height < 16) return TINYEXR_ERROR_INVALID_ARGUMENT;
-
EXRHeader header;
InitEXRHeader(&header);
+ if ((width < 16) && (height < 16)) {
+ // No compression for small image.
+ header.compression_type = TINYEXR_COMPRESSIONTYPE_NONE;
+ } else {
+ header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
+ }
+
EXRImage image;
InitEXRImage(&image);
@@ -12980,8 +13082,7 @@ int SaveEXR(const float *data, int width, int height, int components,
}
}
- const char *err;
- int ret = SaveEXRImageToFile(&image, &header, outfilename, &err);
+ int ret = SaveEXRImageToFile(&image, &header, outfilename, err);
if (ret != TINYEXR_SUCCESS) {
return ret;
}