diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 5910dc501d9..425836fda14 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1215,7 +1215,7 @@
Default map up vector for 3D navigation maps. See [method NavigationServer.map_set_up].
- Maximum amount of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
+ Maximum amount of characters allowed to send as output from the debugger. Over this value, content is dropped with the message [code]"output overflow, print less text!"[/code]. This helps not to stall the debugger connection.
Maximum number of errors allowed to be sent as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
diff --git a/main/main.cpp b/main/main.cpp
index 0415b0aaa0b..7e2a32f6b35 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -952,15 +952,15 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
// Initialize user data dir.
OS::get_singleton()->ensure_user_data_dir();
- GLOBAL_DEF("memory/limits/multithreaded_server/rid_pool_prealloc", 60);
+ GLOBAL_DEF_RST("memory/limits/multithreaded_server/rid_pool_prealloc", 60);
ProjectSettings::get_singleton()->set_custom_property_info("memory/limits/multithreaded_server/rid_pool_prealloc", PropertyInfo(Variant::INT, "memory/limits/multithreaded_server/rid_pool_prealloc", PROPERTY_HINT_RANGE, "0,500,1")); // No negative and limit to 500 due to crashes
- GLOBAL_DEF("network/limits/debugger_stdout/max_chars_per_second", 2048);
+ GLOBAL_DEF_RST("network/limits/debugger_stdout/max_chars_per_second", 2048);
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger_stdout/max_chars_per_second", PropertyInfo(Variant::INT, "network/limits/debugger_stdout/max_chars_per_second", PROPERTY_HINT_RANGE, "0, 4096, 1, or_greater"));
- GLOBAL_DEF("network/limits/debugger_stdout/max_messages_per_frame", 10);
+ GLOBAL_DEF_RST("network/limits/debugger_stdout/max_messages_per_frame", 10);
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger_stdout/max_messages_per_frame", PropertyInfo(Variant::INT, "network/limits/debugger_stdout/max_messages_per_frame", PROPERTY_HINT_RANGE, "0, 20, 1, or_greater"));
- GLOBAL_DEF("network/limits/debugger_stdout/max_errors_per_second", 100);
+ GLOBAL_DEF_RST("network/limits/debugger_stdout/max_errors_per_second", 100);
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger_stdout/max_errors_per_second", PropertyInfo(Variant::INT, "network/limits/debugger_stdout/max_errors_per_second", PROPERTY_HINT_RANGE, "0, 200, 1, or_greater"));
- GLOBAL_DEF("network/limits/debugger_stdout/max_warnings_per_second", 100);
+ GLOBAL_DEF_RST("network/limits/debugger_stdout/max_warnings_per_second", 100);
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger_stdout/max_warnings_per_second", PropertyInfo(Variant::INT, "network/limits/debugger_stdout/max_warnings_per_second", PROPERTY_HINT_RANGE, "0, 200, 1, or_greater"));
if (debug_mode == "remote") {
diff --git a/methods.py b/methods.py
index a5a4a2fdda5..556795160de 100644
--- a/methods.py
+++ b/methods.py
@@ -944,6 +944,17 @@ def get_compiler_version(env):
return None
+def is_vanilla_clang(env):
+ if not using_clang(env):
+ return False
+ try:
+ version = decode_utf8(subprocess.check_output([env.subst(env["CXX"]), "--version"]).strip())
+ except (subprocess.CalledProcessError, OSError):
+ print("Couldn't parse CXX environment variable to infer compiler version.")
+ return False
+ return not version.startswith("Apple")
+
+
def using_gcc(env):
return "gcc" in os.path.basename(env["CC"])
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index b60b10c67e1..b24a32c9ba0 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -1,6 +1,6 @@
import os
import sys
-from methods import detect_darwin_sdk_path
+from methods import detect_darwin_sdk_path, get_compiler_version, is_vanilla_clang
def is_active():
@@ -78,14 +78,21 @@ def configure(env):
env["osxcross"] = True
if env["arch"] == "arm64":
- print("Building for macOS 10.15+, platform arm64.")
- env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15"])
- env.Append(LINKFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15"])
+ print("Building for macOS 11.0+, platform arm64.")
+ env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"])
+ env.Append(LINKFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"])
else:
print("Building for macOS 10.12+, platform x86-64.")
env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
env.Append(LINKFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
+ cc_version = get_compiler_version(env) or [-1, -1]
+ vanilla = is_vanilla_clang(env)
+
+ # Workaround for Xcode 15 linker bug.
+ if not vanilla and cc_version[0] == 15 and cc_version[1] == 0:
+ env.Prepend(LINKFLAGS=["-ld_classic"])
+
if not "osxcross" in env: # regular native build
if env["macports_clang"] != "no":
mpprefix = os.environ.get("MACPORTS_PREFIX", "/opt/local")
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 0ea6bfac821..b3fff50ae13 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -474,7 +474,7 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
@implementation GodotContentView
- (void)drawRect:(NSRect)dirtyRect {
- if (OS_OSX::singleton->get_main_loop() && OS_OSX::singleton->is_resizing) {
+ if (OS_OSX::singleton->get_main_loop() && (OS_OSX::singleton->get_render_thread_mode() != OS::RENDER_SEPARATE_THREAD) && OS_OSX::singleton->is_resizing) {
Main::force_redraw();
if (!Main::is_iterating()) { // Avoid cyclic loop.
Main::iteration();
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index 0f7227460d5..9a1a10b0d2b 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -1200,6 +1200,51 @@ public:
return valid;
}
+#ifdef WINDOWS_ENABLED
+ void extract_all_files_from_zip(String zip_file_path, String extract_path) {
+ FileAccess *src_f = nullptr;
+ zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+
+ unzFile pkg = unzOpen2(zip_file_path.utf8().get_data(), &io);
+
+ int ret = unzGoToFirstFile(pkg);
+
+ while (ret == UNZ_OK) {
+ // get file name
+ unz_file_info info;
+ char fname[16384];
+ ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0);
+
+ String path = String::utf8(fname);
+
+ //write the files
+ Vector data;
+
+ //read
+ data.resize(info.uncompressed_size);
+ unzOpenCurrentFile(pkg);
+ unzReadCurrentFile(pkg, data.ptrw(), data.size());
+ unzCloseCurrentFile(pkg);
+
+ //check if the subfolder doesn't exist and create it
+ String file_path = extract_path + "/" + path.get_base_dir();
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (!da->dir_exists(file_path)) {
+ da->make_dir_recursive(file_path);
+ }
+ memdelete(da);
+
+ FileAccess *unzipped_file = FileAccess::open(extract_path + "/" + path, FileAccess::WRITE);
+ unzipped_file->store_buffer(data.ptrw(), data.size());
+ unzipped_file->close();
+
+ ret = unzGoToNextFile(pkg);
+ }
+
+ unzClose(pkg);
+ }
+#endif
+
virtual Error export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags = 0) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
@@ -1389,6 +1434,50 @@ public:
packager.finish();
#ifdef WINDOWS_ENABLED
+ // Repackage it with makeappx if available
+ String makeappx_path = EditorSettings::get_singleton()->get("export/uwp/makeappx");
+ if (makeappx_path != String()) {
+ if (FileAccess::exists(makeappx_path)) {
+ // Get uwp_temp_path
+ String uwp_temp_path = EditorSettings::get_singleton()->get_cache_dir() + "/uwptemp";
+
+ // Extract current appx file
+ extract_all_files_from_zip(p_path, uwp_temp_path);
+
+ // Call makeappx
+ List args_makeappx;
+ args_makeappx.push_back("pack");
+ args_makeappx.push_back("/d");
+ args_makeappx.push_back(uwp_temp_path);
+ args_makeappx.push_back("/p");
+ args_makeappx.push_back(p_path);
+ args_makeappx.push_back("/o");
+
+ OS::get_singleton()->execute(makeappx_path, args_makeappx, true);
+
+ // Delete uwp_temp_path folder recursively
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Error err = da->change_dir(uwp_temp_path);
+ if (err == OK) {
+ err = da->erase_contents_recursive();
+ if (err != OK) {
+ ERR_PRINT("Could not delete UWP temporary folder: '" + uwp_temp_path + "'.");
+ return err;
+ } else {
+ da->remove(uwp_temp_path);
+ }
+ } else {
+ ERR_PRINT("Could not change dir to UWP temporary folder: '" + uwp_temp_path + "'.");
+ ERR_PRINT("Could not delete UWP temporary folder: '" + uwp_temp_path + "'.");
+ return err;
+ }
+ memdelete(da);
+ } else {
+ ERR_PRINT("Could not find makeappx executable at " + makeappx_path + ", aborting.");
+ return ERR_FILE_NOT_FOUND;
+ }
+ }
+
// Sign with signtool
String signtool_path = EditorSettings::get_singleton()->get("export/uwp/signtool");
if (signtool_path == String()) {
@@ -1466,6 +1555,8 @@ void register_uwp_exporter() {
#ifdef WINDOWS_ENABLED
EDITOR_DEF("export/uwp/signtool", "");
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/uwp/signtool", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
+ EDITOR_DEF("export/uwp/makeappx", "");
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/uwp/makeappx", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
EDITOR_DEF("export/uwp/debug_certificate", "");
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/uwp/debug_certificate", PROPERTY_HINT_GLOBAL_FILE, "*.pfx"));
EDITOR_DEF("export/uwp/debug_password", "");
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 4d204cc1e46..6e80dd1494e 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -31,6 +31,7 @@
#include "button.h"
#include "core/translation.h"
+#include "scene/scene_string_names.h"
#include "servers/visual_server.h"
Size2 Button::get_minimum_size() const {
@@ -301,7 +302,13 @@ void Button::set_icon(const Ref &p_icon) {
if (icon == p_icon) {
return;
}
+ if (icon.is_valid()) {
+ icon->disconnect(SceneStringNames::get_singleton()->changed, this, "_texture_changed");
+ }
icon = p_icon;
+ if (icon.is_valid()) {
+ icon->connect(SceneStringNames::get_singleton()->changed, this, "_texture_changed");
+ }
update();
_change_notify("icon");
minimum_size_changed();
@@ -311,6 +318,11 @@ Ref Button::get_icon() const {
return icon;
}
+void Button::_texture_changed() {
+ update();
+ minimum_size_changed();
+}
+
void Button::set_expand_icon(bool p_expand_icon) {
expand_icon = p_expand_icon;
update();
@@ -376,6 +388,8 @@ void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_expand_icon", "enabled"), &Button::set_expand_icon);
ClassDB::bind_method(D_METHOD("is_expand_icon"), &Button::is_expand_icon);
+ ClassDB::bind_method(D_METHOD("_texture_changed"), &Button::_texture_changed);
+
BIND_ENUM_CONSTANT(ALIGN_LEFT);
BIND_ENUM_CONSTANT(ALIGN_CENTER);
BIND_ENUM_CONSTANT(ALIGN_RIGHT);
diff --git a/scene/gui/button.h b/scene/gui/button.h
index 82e5ba81985..c3ad26202d8 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -54,6 +54,8 @@ private:
TextAlign icon_align;
float _internal_margin[4];
+ void _texture_changed();
+
protected:
void _set_internal_margin(Margin p_margin, float p_value);
void _notification(int p_what);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index ef9ef67b5cf..585e6b066ff 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -4932,7 +4932,7 @@ Rect2 TextEdit::get_rect_at_line_column(int p_line, int p_column) const {
int first_visible_char = cache_entry.first_visible_char[wrap_index];
int last_visible_char = cache_entry.last_visible_char[wrap_index];
- if (p_column < first_visible_char || p_column > last_visible_char) {
+ if (p_column < first_visible_char || p_column > (last_visible_char + 1)) {
// Character is outside of the viewing area, no point calculating its position.
return Rect2i(-1, -1, 0, 0);
}
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index e193ec5262e..b8c653846db 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -29,7 +29,10 @@
/**************************************************************************/
#include "texture_button.h"
+
#include "core/typedefs.h"
+#include "scene/scene_string_names.h"
+
#include
Size2 TextureButton::get_minimum_size() const {
@@ -272,6 +275,8 @@ void TextureButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_expand"), &TextureButton::get_expand);
ClassDB::bind_method(D_METHOD("get_stretch_mode"), &TextureButton::get_stretch_mode);
+ ClassDB::bind_method(D_METHOD("_texture_changed"), &TextureButton::_texture_changed);
+
ADD_GROUP("Textures", "texture_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_texture", "get_normal_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_pressed", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_pressed_texture", "get_pressed_texture");
@@ -294,25 +299,21 @@ void TextureButton::_bind_methods() {
}
void TextureButton::set_normal_texture(const Ref &p_normal) {
- normal = p_normal;
- update();
- minimum_size_changed();
+ _set_texture(&normal, p_normal);
}
void TextureButton::set_pressed_texture(const Ref &p_pressed) {
- pressed = p_pressed;
- update();
- minimum_size_changed();
+ _set_texture(&pressed, p_pressed);
}
+
void TextureButton::set_hover_texture(const Ref &p_hover) {
- hover = p_hover;
- update();
- minimum_size_changed();
+ _set_texture(&hover, p_hover);
}
+
void TextureButton::set_disabled_texture(const Ref &p_disabled) {
- disabled = p_disabled;
- update();
+ _set_texture(&disabled, p_disabled);
}
+
void TextureButton::set_click_mask(const Ref &p_click_mask) {
click_mask = p_click_mask;
update();
@@ -343,6 +344,27 @@ void TextureButton::set_focused_texture(const Ref &p_focused) {
focused = p_focused;
};
+void TextureButton::_set_texture(Ref *p_destination, const Ref &p_texture) {
+ DEV_ASSERT(p_destination);
+ Ref &destination = *p_destination;
+ if (destination == p_texture) {
+ return;
+ }
+ if (destination.is_valid()) {
+ destination->disconnect(SceneStringNames::get_singleton()->changed, this, "_texture_changed");
+ }
+ destination = p_texture;
+ if (destination.is_valid()) {
+ destination->connect(SceneStringNames::get_singleton()->changed, this, "_texture_changed", varray(), CONNECT_REFERENCE_COUNTED);
+ }
+ _texture_changed();
+}
+
+void TextureButton::_texture_changed() {
+ update();
+ minimum_size_changed();
+}
+
bool TextureButton::get_expand() const {
return expand;
}
diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h
index 7f9bbeb8013..81b19b3402f 100644
--- a/scene/gui/texture_button.h
+++ b/scene/gui/texture_button.h
@@ -64,6 +64,9 @@ private:
bool hflip;
bool vflip;
+ void _set_texture(Ref *p_destination, const Ref &p_texture);
+ void _texture_changed();
+
protected:
virtual Size2 get_minimum_size() const;
virtual bool has_point(const Point2 &p_point) const;
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 2b19c565847..6e68080b86a 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -267,7 +267,7 @@ from the Android NDK r18.
## libwebp
- Upstream: https://chromium.googlesource.com/webm/libwebp/
-- Version: 1.3.1 (fd7bb21c0cb56e8a82e9bfa376164b842f433f3b, 2023)
+- Version: 1.3.2 (ca332209cb5567c9b249c86788cb2dbf8847e760, 2023)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -289,7 +289,8 @@ File extracted from upstream release tarball:
- The `LICENSE` file.
- Applied the patch in `patches/1453.diff` to fix UWP build (upstream PR:
https://github.com/ARMmbed/mbedtls/pull/1453).
- Applied the patch in `patches/windows-arm64-hardclock.diff`
+ Applied the patch in `patches/windows-arm64-hardclock.diff`.
+ Applied the patch in `aesni-no-arm-intrinsics.patch` also to fix UWP build.
- Added 2 files `godot_core_mbedtls_platform.c` and `godot_core_mbedtls_config.h`
providing configuration for light bundling with core.
diff --git a/thirdparty/libwebp/src/dec/vp8i_dec.h b/thirdparty/libwebp/src/dec/vp8i_dec.h
index 1ae4ff62f2a..7929fd7506a 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 3
-#define DEC_REV_VERSION 1
+#define DEC_REV_VERSION 2
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y),
diff --git a/thirdparty/libwebp/src/dec/vp8l_dec.c b/thirdparty/libwebp/src/dec/vp8l_dec.c
index c0ea0181e52..7995313fa19 100644
--- a/thirdparty/libwebp/src/dec/vp8l_dec.c
+++ b/thirdparty/libwebp/src/dec/vp8l_dec.c
@@ -253,11 +253,11 @@ static int ReadHuffmanCodeLengths(
int symbol;
int max_symbol;
int prev_code_len = DEFAULT_CODE_LENGTH;
- HuffmanCode table[1 << LENGTHS_TABLE_BITS];
+ HuffmanTables tables;
- if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS,
- code_length_code_lengths,
- NUM_CODE_LENGTH_CODES)) {
+ if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) ||
+ !VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS,
+ code_length_code_lengths, NUM_CODE_LENGTH_CODES)) {
goto End;
}
@@ -277,7 +277,7 @@ static int ReadHuffmanCodeLengths(
int code_len;
if (max_symbol-- == 0) break;
VP8LFillBitWindow(br);
- p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
+ p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
VP8LSetBitPos(br, br->bit_pos_ + p->bits);
code_len = p->value;
if (code_len < kCodeLengthLiterals) {
@@ -300,6 +300,7 @@ static int ReadHuffmanCodeLengths(
ok = 1;
End:
+ VP8LHuffmanTablesDeallocate(&tables);
if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
return ok;
}
@@ -307,7 +308,8 @@ static int ReadHuffmanCodeLengths(
// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
// tree.
static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
- int* const code_lengths, HuffmanCode* const table) {
+ int* const code_lengths,
+ HuffmanTables* const table) {
int ok = 0;
int size = 0;
VP8LBitReader* const br = &dec->br_;
@@ -362,8 +364,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL;
- HuffmanCode* huffman_tables = NULL;
- HuffmanCode* huffman_table = NULL;
+ HuffmanTables* huffman_tables = &hdr->huffman_tables_;
int num_htree_groups = 1;
int num_htree_groups_max = 1;
int max_alphabet_size = 0;
@@ -372,6 +373,10 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int* mapping = NULL;
int ok = 0;
+ // Check the table has been 0 initialized (through InitMetadata).
+ assert(huffman_tables->root.start == NULL);
+ assert(huffman_tables->curr_segment == NULL);
+
if (allow_recursion && VP8LReadBits(br, 1)) {
// use meta Huffman codes.
const int huffman_precision = VP8LReadBits(br, 3) + 2;
@@ -434,16 +439,15 @@ 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);
- if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
+ if (htree_groups == NULL || code_lengths == NULL ||
+ !VP8LHuffmanTablesAllocate(num_htree_groups * table_size,
+ huffman_tables)) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
goto Error;
}
- huffman_table = huffman_tables;
for (i = 0; i < num_htree_groups_max; ++i) {
// If the index "i" is unused in the Huffman image, just make sure the
// coefficients are valid but do not store them.
@@ -468,19 +472,20 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
- htrees[j] = huffman_table;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += (1 << color_cache_bits);
}
- size = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_table);
+ size =
+ ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);
+ htrees[j] = huffman_tables->curr_segment->curr_table;
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
- is_trivial_literal = (huffman_table->bits == 0);
+ is_trivial_literal = (htrees[j]->bits == 0);
}
- total_size += huffman_table->bits;
- huffman_table += size;
+ total_size += htrees[j]->bits;
+ huffman_tables->curr_segment->curr_table += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
@@ -515,14 +520,13 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
hdr->huffman_image_ = huffman_image;
hdr->num_htree_groups_ = num_htree_groups;
hdr->htree_groups_ = htree_groups;
- hdr->huffman_tables_ = huffman_tables;
Error:
WebPSafeFree(code_lengths);
WebPSafeFree(mapping);
if (!ok) {
WebPSafeFree(huffman_image);
- WebPSafeFree(huffman_tables);
+ VP8LHuffmanTablesDeallocate(huffman_tables);
VP8LHtreeGroupsFree(htree_groups);
}
return ok;
@@ -1358,7 +1362,7 @@ static void ClearMetadata(VP8LMetadata* const hdr) {
assert(hdr != NULL);
WebPSafeFree(hdr->huffman_image_);
- WebPSafeFree(hdr->huffman_tables_);
+ VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_);
VP8LHtreeGroupsFree(hdr->htree_groups_);
VP8LColorCacheClear(&hdr->color_cache_);
VP8LColorCacheClear(&hdr->saved_color_cache_);
@@ -1673,7 +1677,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
if (dec == NULL) return 0;
- assert(dec->hdr_.huffman_tables_ != NULL);
+ assert(dec->hdr_.huffman_tables_.root.start != NULL);
assert(dec->hdr_.htree_groups_ != NULL);
assert(dec->hdr_.num_htree_groups_ > 0);
diff --git a/thirdparty/libwebp/src/dec/vp8li_dec.h b/thirdparty/libwebp/src/dec/vp8li_dec.h
index 72b2e861208..32540a4b88a 100644
--- a/thirdparty/libwebp/src/dec/vp8li_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8li_dec.h
@@ -51,7 +51,7 @@ typedef struct {
uint32_t* huffman_image_;
int num_htree_groups_;
HTreeGroup* htree_groups_;
- HuffmanCode* huffman_tables_;
+ HuffmanTables huffman_tables_;
} VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder;
diff --git a/thirdparty/libwebp/src/demux/demux.c b/thirdparty/libwebp/src/demux/demux.c
index fd45a2500e4..4b0d3f59e91 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 3
-#define DMUX_REV_VERSION 1
+#define DMUX_REV_VERSION 2
typedef struct {
size_t start_; // start location of the data
diff --git a/thirdparty/libwebp/src/enc/vp8i_enc.h b/thirdparty/libwebp/src/enc/vp8i_enc.h
index 19d9a6edb77..0864fbf1f51 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 3
-#define ENC_REV_VERSION 1
+#define ENC_REV_VERSION 2
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
diff --git a/thirdparty/libwebp/src/mux/muxi.h b/thirdparty/libwebp/src/mux/muxi.h
index fc44d6f2feb..afc59543533 100644
--- a/thirdparty/libwebp/src/mux/muxi.h
+++ b/thirdparty/libwebp/src/mux/muxi.h
@@ -29,7 +29,7 @@ extern "C" {
#define MUX_MAJ_VERSION 1
#define MUX_MIN_VERSION 3
-#define MUX_REV_VERSION 1
+#define MUX_REV_VERSION 2
// Chunk object.
typedef struct WebPChunk WebPChunk;
diff --git a/thirdparty/libwebp/src/utils/huffman_utils.c b/thirdparty/libwebp/src/utils/huffman_utils.c
index 90c2fbf7c18..cf73abd437d 100644
--- a/thirdparty/libwebp/src/utils/huffman_utils.c
+++ b/thirdparty/libwebp/src/utils/huffman_utils.c
@@ -177,21 +177,24 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
if (num_open < 0) {
return 0;
}
- if (root_table == NULL) continue;
for (; count[len] > 0; --count[len]) {
HuffmanCode code;
if ((key & mask) != low) {
- table += table_size;
+ if (root_table != NULL) table += table_size;
table_bits = NextTableBitSize(count, len, root_bits);
table_size = 1 << table_bits;
total_size += table_size;
low = key & mask;
- root_table[low].bits = (uint8_t)(table_bits + root_bits);
- root_table[low].value = (uint16_t)((table - root_table) - low);
+ if (root_table != NULL) {
+ root_table[low].bits = (uint8_t)(table_bits + root_bits);
+ root_table[low].value = (uint16_t)((table - root_table) - low);
+ }
+ }
+ if (root_table != NULL) {
+ code.bits = (uint8_t)(len - root_bits);
+ code.value = (uint16_t)sorted[symbol++];
+ ReplicateValue(&table[key >> root_bits], step, table_size, code);
}
- code.bits = (uint8_t)(len - root_bits);
- code.value = (uint16_t)sorted[symbol++];
- ReplicateValue(&table[key >> root_bits], step, table_size, code);
key = GetNextKey(key, len);
}
}
@@ -211,25 +214,83 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES)
// Cut-off value for switching between heap and stack allocation.
#define SORTED_SIZE_CUTOFF 512
-int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
+int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits,
const int code_lengths[], int code_lengths_size) {
- int total_size;
+ const int total_size =
+ BuildHuffmanTable(NULL, root_bits, code_lengths, code_lengths_size, NULL);
assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);
- if (root_table == NULL) {
- total_size = BuildHuffmanTable(NULL, root_bits,
- code_lengths, code_lengths_size, NULL);
- } else if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
+ if (total_size == 0 || root_table == NULL) return total_size;
+
+ if (root_table->curr_segment->curr_table + total_size >=
+ root_table->curr_segment->start + root_table->curr_segment->size) {
+ // If 'root_table' does not have enough memory, allocate a new segment.
+ // The available part of root_table->curr_segment is left unused because we
+ // need a contiguous buffer.
+ const int segment_size = root_table->curr_segment->size;
+ struct HuffmanTablesSegment* next =
+ (HuffmanTablesSegment*)WebPSafeMalloc(1, sizeof(*next));
+ if (next == NULL) return 0;
+ // Fill the new segment.
+ // We need at least 'total_size' but if that value is small, it is better to
+ // allocate a big chunk to prevent more allocations later. 'segment_size' is
+ // therefore chosen (any other arbitrary value could be chosen).
+ next->size = total_size > segment_size ? total_size : segment_size;
+ next->start =
+ (HuffmanCode*)WebPSafeMalloc(next->size, sizeof(*next->start));
+ if (next->start == NULL) {
+ WebPSafeFree(next);
+ return 0;
+ }
+ next->curr_table = next->start;
+ next->next = NULL;
+ // Point to the new segment.
+ root_table->curr_segment->next = next;
+ root_table->curr_segment = next;
+ }
+ if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
// use local stack-allocated array.
uint16_t sorted[SORTED_SIZE_CUTOFF];
- total_size = BuildHuffmanTable(root_table, root_bits,
- code_lengths, code_lengths_size, sorted);
- } else { // rare case. Use heap allocation.
+ BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits,
+ code_lengths, code_lengths_size, sorted);
+ } else { // rare case. Use heap allocation.
uint16_t* const sorted =
(uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
if (sorted == NULL) return 0;
- total_size = BuildHuffmanTable(root_table, root_bits,
- code_lengths, code_lengths_size, sorted);
+ BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits,
+ code_lengths, code_lengths_size, sorted);
WebPSafeFree(sorted);
}
return total_size;
}
+
+int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables) {
+ // Have 'segment' point to the first segment for now, 'root'.
+ HuffmanTablesSegment* const root = &huffman_tables->root;
+ huffman_tables->curr_segment = root;
+ // Allocate root.
+ root->start = (HuffmanCode*)WebPSafeMalloc(size, sizeof(*root->start));
+ if (root->start == NULL) return 0;
+ root->curr_table = root->start;
+ root->next = NULL;
+ root->size = size;
+ return 1;
+}
+
+void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables) {
+ HuffmanTablesSegment *current, *next;
+ if (huffman_tables == NULL) return;
+ // Free the root node.
+ current = &huffman_tables->root;
+ next = current->next;
+ WebPSafeFree(current->start);
+ current->start = NULL;
+ current->next = NULL;
+ current = next;
+ // Free the following nodes.
+ while (current != NULL) {
+ next = current->next;
+ WebPSafeFree(current->start);
+ WebPSafeFree(current);
+ current = next;
+ }
+}
diff --git a/thirdparty/libwebp/src/utils/huffman_utils.h b/thirdparty/libwebp/src/utils/huffman_utils.h
index 13b7ad1ac40..98415c53289 100644
--- a/thirdparty/libwebp/src/utils/huffman_utils.h
+++ b/thirdparty/libwebp/src/utils/huffman_utils.h
@@ -43,6 +43,29 @@ typedef struct {
// or non-literal symbol otherwise
} HuffmanCode32;
+// Contiguous memory segment of HuffmanCodes.
+typedef struct HuffmanTablesSegment {
+ HuffmanCode* start;
+ // Pointer to where we are writing into the segment. Starts at 'start' and
+ // cannot go beyond 'start' + 'size'.
+ HuffmanCode* curr_table;
+ // Pointer to the next segment in the chain.
+ struct HuffmanTablesSegment* next;
+ int size;
+} HuffmanTablesSegment;
+
+// Chained memory segments of HuffmanCodes.
+typedef struct HuffmanTables {
+ HuffmanTablesSegment root;
+ // Currently processed segment. At first, this is 'root'.
+ HuffmanTablesSegment* curr_segment;
+} HuffmanTables;
+
+// Allocates a HuffmanTables with 'size' contiguous HuffmanCodes. Returns 0 on
+// memory allocation error, 1 otherwise.
+int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables);
+void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables);
+
#define HUFFMAN_PACKED_BITS 6
#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS)
@@ -78,9 +101,7 @@ void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups);
// the huffman table.
// Returns built table size or 0 in case of error (invalid tree or
// memory error).
-// If root_table is NULL, it returns 0 if a lookup cannot be built, something
-// > 0 otherwise (but not the table size).
-int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
+int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits,
const int code_lengths[], int code_lengths_size);
#ifdef __cplusplus
diff --git a/thirdparty/mbedtls/include/mbedtls/aesni.h b/thirdparty/mbedtls/include/mbedtls/aesni.h
index 6741dead05b..6c545bd4a31 100644
--- a/thirdparty/mbedtls/include/mbedtls/aesni.h
+++ b/thirdparty/mbedtls/include/mbedtls/aesni.h
@@ -54,9 +54,10 @@
* macros that may change in future releases.
*/
#undef MBEDTLS_AESNI_HAVE_INTRINSICS
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_IX86))
/* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support
- * VS 2013 and up for other reasons anyway, so no need to check the version. */
+ * VS 2013 and up for other reasons anyway, so no need to check the version.
+ * Only supported on x64 and x86. */
#define MBEDTLS_AESNI_HAVE_INTRINSICS
#endif
/* GCC-like compilers: currently, we only support intrinsics if the requisite
diff --git a/thirdparty/mbedtls/patches/aesni-no-arm-intrinsics.patch b/thirdparty/mbedtls/patches/aesni-no-arm-intrinsics.patch
new file mode 100644
index 00000000000..7edfa072d89
--- /dev/null
+++ b/thirdparty/mbedtls/patches/aesni-no-arm-intrinsics.patch
@@ -0,0 +1,17 @@
+diff --git a/thirdparty/mbedtls/include/mbedtls/aesni.h b/thirdparty/mbedtls/include/mbedtls/aesni.h
+index 6741dead05..6c545bd4a3 100644
+--- a/thirdparty/mbedtls/include/mbedtls/aesni.h
++++ b/thirdparty/mbedtls/include/mbedtls/aesni.h
+@@ -54,9 +54,10 @@
+ * macros that may change in future releases.
+ */
+ #undef MBEDTLS_AESNI_HAVE_INTRINSICS
+-#if defined(_MSC_VER)
++#if defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_IX86))
+ /* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support
+- * VS 2013 and up for other reasons anyway, so no need to check the version. */
++ * VS 2013 and up for other reasons anyway, so no need to check the version.
++ * Only supported on x64 and x86. */
+ #define MBEDTLS_AESNI_HAVE_INTRINSICS
+ #endif
+ /* GCC-like compilers: currently, we only support intrinsics if the requisite