diff options
Diffstat (limited to 'thirdparty')
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; } |