summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/mono/csharp_script.cpp112
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp35
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h23
-rw-r--r--platform/x11/detect.py12
-rw-r--r--platform/x11/pck_embed.ld4
-rw-r--r--platform/x11/pck_embed.legacy.ld10
-rw-r--r--thirdparty/README.md2
-rw-r--r--thirdparty/libwebp/src/dec/frame_dec.c2
-rw-r--r--thirdparty/libwebp/src/dec/idec_dec.c11
-rw-r--r--thirdparty/libwebp/src/dec/vp8i_dec.h4
-rw-r--r--thirdparty/libwebp/src/dec/vp8l_dec.c10
-rw-r--r--thirdparty/libwebp/src/dec/vp8li_dec.h20
-rw-r--r--thirdparty/libwebp/src/demux/demux.c4
-rw-r--r--thirdparty/libwebp/src/dsp/dec_neon.c9
-rw-r--r--thirdparty/libwebp/src/dsp/dsp.h4
-rw-r--r--thirdparty/libwebp/src/dsp/lossless.c11
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_common.h2
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc_sse2.c3
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_sse2.c3
-rw-r--r--thirdparty/libwebp/src/dsp/upsampling_msa.c4
-rw-r--r--thirdparty/libwebp/src/dsp/upsampling_neon.c14
-rw-r--r--thirdparty/libwebp/src/enc/histogram_enc.c2
-rw-r--r--thirdparty/libwebp/src/enc/picture_csp_enc.c18
-rw-r--r--thirdparty/libwebp/src/enc/vp8i_enc.h6
-rw-r--r--thirdparty/libwebp/src/mux/muxi.h4
-rw-r--r--thirdparty/libwebp/src/mux/muxread.c2
-rw-r--r--thirdparty/libwebp/src/utils/color_cache_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/thread_utils.c2
-rw-r--r--thirdparty/libwebp/src/utils/utils.c9
-rw-r--r--thirdparty/libwebp/src/webp/decode.h5
-rw-r--r--thirdparty/libwebp/src/webp/encode.h9
-rw-r--r--thirdparty/libwebp/src/webp/mux.h12
-rw-r--r--thirdparty/libwebp/src/webp/mux_types.h10
-rw-r--r--thirdparty/libwebp/src/webp/types.h18
34 files changed, 270 insertions, 128 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 3678a82bee..0f6b8357b8 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -559,6 +559,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info()
#ifdef DEBUG_ENABLED
_TLS_RECURSION_GUARD_V_(Vector<StackInfo>());
+ GD_MONO_SCOPE_THREAD_ATTACH;
if (!gdmono->is_runtime_initialized() || !GDMono::get_singleton()->get_core_api_assembly() || !GDMonoCache::cached_data.corlib_cache_updated)
return Vector<StackInfo>();
@@ -583,6 +584,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info()
Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObject *p_stack_trace) {
_TLS_RECURSION_GUARD_V_(Vector<StackInfo>());
+ GD_MONO_SCOPE_THREAD_ATTACH;
MonoException *exc = NULL;
@@ -689,6 +691,7 @@ void CSharpLanguage::reload_all_scripts() {
#ifdef GD_MONO_HOT_RELOAD
if (is_assembly_reloading_needed()) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
reload_assemblies(false);
}
#endif
@@ -706,6 +709,7 @@ void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft
#ifdef GD_MONO_HOT_RELOAD
if (is_assembly_reloading_needed()) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
reload_assemblies(p_soft_reload);
}
#endif
@@ -1356,6 +1360,8 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) {
if (finalizing)
return; // inside CSharpLanguage::finish(), all the gchandle bindings are released there
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
{
SCOPED_MUTEX_LOCK(language_bind_mutex);
@@ -1382,6 +1388,7 @@ void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
#ifdef DEBUG_ENABLED
CRASH_COND(!ref_owner);
+ CRASH_COND(!p_object->has_script_instance_binding(get_language_index()));
#endif
void *data = p_object->get_script_instance_binding(get_language_index());
@@ -1394,6 +1401,8 @@ void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
return;
if (ref_owner->reference_get_count() > 1 && gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
// The reference count was increased after the managed side was the only one referencing our owner.
// This means the owner is being referenced again by the unmanaged side,
// so the owner must hold the managed side alive again to avoid it from being GCed.
@@ -1415,6 +1424,7 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
#ifdef DEBUG_ENABLED
CRASH_COND(!ref_owner);
+ CRASH_COND(!p_object->has_script_instance_binding(get_language_index()));
#endif
void *data = p_object->get_script_instance_binding(get_language_index());
@@ -1429,6 +1439,8 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
return refcount == 0;
if (refcount == 1 && gchandle.is_valid() && !gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
// If owner owner is no longer referenced by the unmanaged side,
// the managed instance takes responsibility of deleting the owner when GCed.
@@ -1480,6 +1492,8 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(!script.is_valid(), false);
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
MonoObject *mono_object = get_mono_object();
ERR_FAIL_NULL_V(mono_object, false);
@@ -1532,6 +1546,8 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const {
ERR_FAIL_COND_V(!script.is_valid(), false);
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
MonoObject *mono_object = get_mono_object();
ERR_FAIL_NULL_V(mono_object, false);
@@ -1625,6 +1641,8 @@ void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
ERR_FAIL_COND(!script.is_valid());
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
MonoObject *mono_object = get_mono_object();
ERR_FAIL_NULL(mono_object);
@@ -1669,6 +1687,8 @@ bool CSharpInstance::has_method(const StringName &p_method) const {
if (!script.is_valid())
return false;
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
@@ -1684,6 +1704,11 @@ bool CSharpInstance::has_method(const StringName &p_method) const {
Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+ if (!script.is_valid())
+ ERR_FAIL_V(Variant());
+
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
MonoObject *mono_object = get_mono_object();
if (!mono_object) {
@@ -1691,9 +1716,6 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args,
ERR_FAIL_V(Variant());
}
- if (!script.is_valid())
- ERR_FAIL_V(Variant());
-
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
@@ -1721,6 +1743,8 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args,
void CSharpInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
if (script.is_valid()) {
MonoObject *mono_object = get_mono_object();
@@ -1732,6 +1756,8 @@ void CSharpInstance::call_multilevel(const StringName &p_method, const Variant *
void CSharpInstance::_call_multilevel(MonoObject *p_mono_object, const StringName &p_method, const Variant **p_args, int p_argcount) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
@@ -1894,6 +1920,8 @@ void CSharpInstance::refcount_incremented() {
Reference *ref_owner = Object::cast_to<Reference>(owner);
if (ref_owner->reference_get_count() > 1 && gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
// The reference count was increased after the managed side was the only one referencing our owner.
// This means the owner is being referenced again by the unmanaged side,
// so the owner must hold the managed side alive again to avoid it from being GCed.
@@ -1917,6 +1945,8 @@ bool CSharpInstance::refcount_decremented() {
int refcount = ref_owner->reference_get_count();
if (refcount == 1 && !gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
// If owner owner is no longer referenced by the unmanaged side,
// the managed instance takes responsibility of deleting the owner when GCed.
@@ -1957,6 +1987,8 @@ MultiplayerAPI::RPCMode CSharpInstance::_member_get_rpc_mode(IMonoClassMember *p
MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
@@ -1973,6 +2005,8 @@ MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method)
MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
@@ -1994,6 +2028,8 @@ MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variab
void CSharpInstance::notification(int p_notification) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
if (p_notification == Object::NOTIFICATION_PREDELETE) {
// When NOTIFICATION_PREDELETE is sent, we also take the chance to call Dispose().
// It's safe to call Dispose() multiple times and NOTIFICATION_PREDELETE is guaranteed
@@ -2031,6 +2067,8 @@ void CSharpInstance::notification(int p_notification) {
void CSharpInstance::_call_notification(int p_notification) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
MonoObject *mono_object = get_mono_object();
ERR_FAIL_NULL(mono_object);
@@ -2055,6 +2093,8 @@ void CSharpInstance::_call_notification(int p_notification) {
}
String CSharpInstance::to_string(bool *r_valid) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
MonoObject *mono_object = get_mono_object();
if (mono_object == NULL) {
@@ -2103,6 +2143,8 @@ CSharpInstance::CSharpInstance() :
CSharpInstance::~CSharpInstance() {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
destructing_script_instance = true;
if (gchandle.is_valid()) {
@@ -2206,6 +2248,8 @@ void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List
void CSharpScript::_update_member_info_no_exports() {
if (exports_invalidated) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
exports_invalidated = false;
member_info.clear();
@@ -2264,6 +2308,8 @@ bool CSharpScript::_update_exports() {
bool changed = false;
if (exports_invalidated) {
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
exports_invalidated = false;
changed = true;
@@ -2413,6 +2459,8 @@ void CSharpScript::load_script_signals(GDMonoClass *p_class, GDMonoClass *p_nati
// make sure this classes signals are empty when loading for the first time
_signals.clear();
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = p_class;
while (top && top != p_native_class) {
const Vector<GDMonoClass *> &delegates = top->get_all_delegates();
@@ -2433,6 +2481,8 @@ void CSharpScript::load_script_signals(GDMonoClass *p_class, GDMonoClass *p_nati
}
bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Vector<Argument> &params) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
if (p_delegate->has_attribute(CACHED_CLASS(SignalAttribute))) {
MonoType *raw_type = p_delegate->get_mono_type();
@@ -2474,6 +2524,8 @@ bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Ve
*/
bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
// Goddammit, C++. All I wanted was some nested functions.
#define MEMBER_FULL_QUALIFIED_NAME(m_member) \
(m_member->get_enclosing_class()->get_full_name() + "." + (String)m_member->get_name())
@@ -2552,6 +2604,8 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect
int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, ManagedType p_type, Variant::Type p_variant_type, bool p_allow_generics, PropertyHint &r_hint, String &r_hint_string) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
if (p_variant_type == Variant::INT && p_type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(p_type.type_class->get_mono_ptr())) {
r_hint = PROPERTY_HINT_ENUM;
@@ -2661,6 +2715,8 @@ Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, i
return Variant();
}
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = script_class;
while (top && top != native) {
@@ -2853,6 +2909,8 @@ StringName CSharpScript::get_instance_base_type() const {
CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error) {
+ GD_MONO_ASSERT_THREAD_ATTACHED;
+
/* STEP 1, CREATE */
// Search the constructor first, to fail with an error if it's not found before allocating anything else.
@@ -2947,12 +3005,14 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Variant::Call
}
r_error.error = Variant::CallError::CALL_OK;
- REF ref;
ERR_FAIL_NULL_V(native, Variant());
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
Object *owner = ClassDB::instance(NATIVE_GDMONOCLASS_NAME(native));
+ REF ref;
Reference *r = Object::cast_to<Reference>(owner);
if (r) {
ref = REF(r);
@@ -2990,6 +3050,8 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) {
}
}
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
Variant::CallError unchecked_error;
return _create_instance(NULL, 0, p_this, Object::cast_to<Reference>(p_this) != NULL, unchecked_error);
}
@@ -3037,6 +3099,8 @@ void CSharpScript::get_script_method_list(List<MethodInfo> *p_list) const {
if (!script_class)
return;
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
// TODO: Filter out things unsuitable for explicit calls, like constructors.
const Vector<GDMonoMethod *> &methods = script_class->get_all_methods();
for (int i = 0; i < methods.size(); ++i) {
@@ -3049,6 +3113,8 @@ bool CSharpScript::has_method(const StringName &p_method) const {
if (!script_class)
return false;
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
return script_class->has_fetched_method_unknown_params(p_method);
}
@@ -3057,6 +3123,8 @@ MethodInfo CSharpScript::get_method_info(const StringName &p_method) const {
if (!script_class)
return MethodInfo();
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoClass *top = script_class;
while (top && top != native) {
@@ -3081,6 +3149,8 @@ Error CSharpScript::reload(bool p_keep_state) {
ERR_FAIL_COND_V(!p_keep_state && has_instances, ERR_ALREADY_IN_USE);
+ GD_MONO_SCOPE_THREAD_ATTACH;
+
GDMonoAssembly *project_assembly = GDMono::get_singleton()->get_project_assembly();
if (project_assembly) {
@@ -3308,39 +3378,7 @@ RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p
script->set_path(p_original_path);
-#ifndef TOOLS_ENABLED
-
-#ifdef DEBUG_ENABLED
- // User is responsible for thread attach/detach
- CRASH_COND_MSG(mono_domain_get() == NULL, "Thread is not attached.");
-#endif
-
-#endif
-
-#ifdef TOOLS_ENABLED
- MonoDomain *domain = mono_domain_get();
- if (Engine::get_singleton()->is_editor_hint() && domain == NULL) {
-
- CRASH_COND(Thread::get_caller_id() == Thread::get_main_id());
-
- // Thread is not attached, but we will make an exception in this case
- // because this may be called by one of the editor's worker threads.
- // Attach this thread temporarily to reload the script.
-
- if (domain) {
- MonoThread *mono_thread = mono_thread_attach(domain);
- CRASH_COND(mono_thread == NULL);
- script->reload();
- mono_thread_detach(mono_thread);
- }
-
- } else { // just reload it normally
-#endif
- script->reload();
-
-#ifdef TOOLS_ENABLED
- }
-#endif
+ script->reload();
if (r_error)
*r_error = OK;
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 6bb9f28a32..4e7f590a69 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -125,10 +125,12 @@ void set_main_thread(MonoThread *p_thread) {
mono_thread_set_main(p_thread);
}
-void attach_current_thread() {
- ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
- MonoThread *mono_thread = mono_thread_attach(mono_get_root_domain());
- ERR_FAIL_NULL(mono_thread);
+MonoThread *attach_current_thread() {
+ ERR_FAIL_COND_V(!GDMono::get_singleton()->is_runtime_initialized(), NULL);
+ MonoDomain *scripts_domain = GDMono::get_singleton()->get_scripts_domain();
+ MonoThread *mono_thread = mono_thread_attach(scripts_domain ? scripts_domain : mono_get_root_domain());
+ ERR_FAIL_NULL_V(mono_thread, NULL);
+ return mono_thread;
}
void detach_current_thread() {
@@ -138,10 +140,20 @@ void detach_current_thread() {
mono_thread_detach(mono_thread);
}
+void detach_current_thread(MonoThread *p_mono_thread) {
+ ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
+ ERR_FAIL_NULL(p_mono_thread);
+ mono_thread_detach(p_mono_thread);
+}
+
MonoThread *get_current_thread() {
return mono_thread_current();
}
+bool is_thread_attached() {
+ return mono_domain_get() != NULL;
+}
+
void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc) {
GDMonoMethod *ctor = p_class->get_method(".ctor", 0);
ERR_FAIL_NULL(ctor);
@@ -617,4 +629,19 @@ GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, Mon
} // namespace Marshal
+ScopeThreadAttach::ScopeThreadAttach() :
+ mono_thread(NULL) {
+ if (likely(GDMono::get_singleton()->is_runtime_initialized()) && unlikely(!mono_domain_get())) {
+ mono_thread = GDMonoUtils::attach_current_thread();
+ }
+}
+
+ScopeThreadAttach::~ScopeThreadAttach() {
+ if (unlikely(mono_thread)) {
+ GDMonoUtils::detach_current_thread(mono_thread);
+ }
+}
+
+// namespace Marshal
+
} // namespace GDMonoUtils
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index d9eb912cd7..db9f99bfdc 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -83,9 +83,11 @@ _FORCE_INLINE_ void hash_combine(uint32_t &p_hash, const uint32_t &p_with_hash)
MonoObject *unmanaged_get_managed(Object *unmanaged);
void set_main_thread(MonoThread *p_thread);
-void attach_current_thread();
+MonoThread *attach_current_thread();
void detach_current_thread();
+void detach_current_thread(MonoThread *p_mono_thread);
MonoThread *get_current_thread();
+bool is_thread_attached();
_FORCE_INLINE_ bool is_main_thread() {
return mono_domain_get() != NULL && mono_thread_get_main() == mono_thread_current();
@@ -142,6 +144,14 @@ uint64_t unbox_enum_value(MonoObject *p_boxed, MonoType *p_enum_basetype, bool &
void dispose(MonoObject *p_mono_object, MonoException **r_exc);
+struct ScopeThreadAttach {
+ ScopeThreadAttach();
+ ~ScopeThreadAttach();
+
+private:
+ MonoThread *mono_thread;
+};
+
} // namespace GDMonoUtils
#define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoMarshal::mono_string_to_godot((MonoString *)m_class->get_field(BINDINGS_NATIVE_NAME_FIELD)->get_value(NULL)))
@@ -153,4 +163,15 @@ void dispose(MonoObject *p_mono_object, MonoException **r_exc);
#define GD_MONO_END_RUNTIME_INVOKE \
_runtime_invoke_count_ref -= 1;
+#define GD_MONO_SCOPE_THREAD_ATTACH \
+ GDMonoUtils::ScopeThreadAttach __gdmono__scope__thread__attach__; \
+ (void)__gdmono__scope__thread__attach__;
+
+#ifdef DEBUG_ENABLED
+#define GD_MONO_ASSERT_THREAD_ATTACHED \
+ { CRASH_COND(!GDMonoUtils::is_thread_attached()); }
+#else
+#define GD_MONO_ASSERT_THREAD_ATTACHED
+#endif
+
#endif // GD_MONOUTILS_H
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index a961072bd6..957779ee83 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -171,7 +171,7 @@ def configure(env):
else:
env.Append(CCFLAGS=['-flto'])
env.Append(LINKFLAGS=['-flto'])
-
+
if not env['use_llvm']:
env['RANLIB'] = 'gcc-ranlib'
env['AR'] = 'gcc-ar'
@@ -329,9 +329,15 @@ def configure(env):
if env["execinfo"]:
env.Append(LIBS=['execinfo'])
-
+
if not env['tools']:
- env.Append(LINKFLAGS=['-T', 'platform/x11/pck_embed.ld'])
+ import subprocess
+ import re
+ binutils_version = re.search('\s(\d+\.\d+)', str(subprocess.check_output(['ld', '-v']))).group(1)
+ if float(binutils_version) >= 2.30:
+ env.Append(LINKFLAGS=['-T', 'platform/x11/pck_embed.ld'])
+ else:
+ env.Append(LINKFLAGS=['-T', 'platform/x11/pck_embed.legacy.ld'])
## Cross-compilation
diff --git a/platform/x11/pck_embed.ld b/platform/x11/pck_embed.ld
index fe09144d88..57a1994043 100644
--- a/platform/x11/pck_embed.ld
+++ b/platform/x11/pck_embed.ld
@@ -1,9 +1,9 @@
SECTIONS
{
/* Add a zero-sized section; the exporter will patch it to enclose the data appended to the executable (embedded PCK) */
- pck 0 (NOLOAD) :
+ pck 0 (INFO) :
{
- /* Just some content to avoid the linker discarding the section */
+ /* binutils >= 2.30 allow it being zero-sized, but needs something between the braces to keep the section */
. = ALIGN(8);
}
}
diff --git a/platform/x11/pck_embed.legacy.ld b/platform/x11/pck_embed.legacy.ld
new file mode 100644
index 0000000000..a23013ba7a
--- /dev/null
+++ b/platform/x11/pck_embed.legacy.ld
@@ -0,0 +1,10 @@
+SECTIONS
+{
+ /* The exporter will patch this section to enclose the data appended to the executable (embedded PCK) */
+ pck 0 (INFO) : AT ( ADDR (.rodata) + SIZEOF (.rodata) )
+ {
+ /* binutils < 2.30 need some actual content for the linker not to discard the section */
+ BYTE(0);
+ }
+}
+INSERT AFTER .rodata;
diff --git a/thirdparty/README.md b/thirdparty/README.md
index b68c585cac..b29f4bd5e8 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -237,7 +237,7 @@ from the Android NDK r18.
## libwebp
- Upstream: https://chromium.googlesource.com/webm/libwebp/
-- Version: 1.0.3
+- Version: 1.1.0
- License: BSD-3-Clause
Files extracted from upstream source:
diff --git a/thirdparty/libwebp/src/dec/frame_dec.c b/thirdparty/libwebp/src/dec/frame_dec.c
index bda9e1a6f6..04609a8e56 100644
--- a/thirdparty/libwebp/src/dec/frame_dec.c
+++ b/thirdparty/libwebp/src/dec/frame_dec.c
@@ -732,7 +732,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
mem += f_info_size;
dec->thread_ctx_.id_ = 0;
dec->thread_ctx_.f_info_ = dec->f_info_;
- if (dec->mt_method_ > 0) {
+ if (dec->filter_type_ > 0 && dec->mt_method_ > 0) {
// secondary cache line. The deblocking process need to make use of the
// filtering strength from previous macroblock row, while the new ones
// are being decoded in parallel. We'll just swap the pointers.
diff --git a/thirdparty/libwebp/src/dec/idec_dec.c b/thirdparty/libwebp/src/dec/idec_dec.c
index 9bc9166808..9035df5659 100644
--- a/thirdparty/libwebp/src/dec/idec_dec.c
+++ b/thirdparty/libwebp/src/dec/idec_dec.c
@@ -166,9 +166,11 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
MemBuffer* const mem = &idec->mem_;
const int need_compressed_alpha = NeedCompressedAlpha(idec);
- const uint8_t* const old_start = mem->buf_ + mem->start_;
+ const uint8_t* const old_start =
+ (mem->buf_ == NULL) ? NULL : mem->buf_ + mem->start_;
const uint8_t* const old_base =
need_compressed_alpha ? dec->alpha_data_ : old_start;
+ assert(mem->buf_ != NULL || mem->start_ == 0);
assert(mem->mode_ == MEM_MODE_APPEND);
if (data_size > MAX_CHUNK_PAYLOAD) {
// security safeguard: trying to allocate more than what the format
@@ -184,7 +186,7 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
uint8_t* const new_buf =
(uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf));
if (new_buf == NULL) return 0;
- memcpy(new_buf, old_base, current_size);
+ if (old_base != NULL) memcpy(new_buf, old_base, current_size);
WebPSafeFree(mem->buf_);
mem->buf_ = new_buf;
mem->buf_size_ = (size_t)extra_size;
@@ -192,6 +194,7 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
mem->end_ = current_size;
}
+ assert(mem->buf_ != NULL);
memcpy(mem->buf_ + mem->end_, data, data_size);
mem->end_ += data_size;
assert(mem->end_ <= mem->buf_size_);
@@ -204,7 +207,9 @@ static int RemapMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data, size_t data_size) {
MemBuffer* const mem = &idec->mem_;
const uint8_t* const old_buf = mem->buf_;
- const uint8_t* const old_start = old_buf + mem->start_;
+ const uint8_t* const old_start =
+ (old_buf == NULL) ? NULL : old_buf + mem->start_;
+ assert(old_buf != NULL || mem->start_ == 0);
assert(mem->mode_ == MEM_MODE_MAP);
if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
diff --git a/thirdparty/libwebp/src/dec/vp8i_dec.h b/thirdparty/libwebp/src/dec/vp8i_dec.h
index 3de8d86f90..600a684410 100644
--- a/thirdparty/libwebp/src/dec/vp8i_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8i_dec.h
@@ -31,8 +31,8 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 1
-#define DEC_MIN_VERSION 0
-#define DEC_REV_VERSION 3
+#define DEC_MIN_VERSION 1
+#define DEC_REV_VERSION 0
// 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 d3e27119ea..93615d4ed2 100644
--- a/thirdparty/libwebp/src/dec/vp8l_dec.c
+++ b/thirdparty/libwebp/src/dec/vp8l_dec.c
@@ -754,11 +754,11 @@ static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
-static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
+static void ApplyInverseTransforms(VP8LDecoder* const dec,
+ int start_row, int num_rows,
const uint32_t* const rows) {
int n = dec->next_transform_;
const int cache_pixs = dec->width_ * num_rows;
- const int start_row = dec->last_row_;
const int end_row = start_row + num_rows;
const uint32_t* rows_in = rows;
uint32_t* const rows_out = dec->argb_cache_;
@@ -789,8 +789,7 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
VP8Io* const io = dec->io_;
uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA
-
- ApplyInverseTransforms(dec, num_rows, rows);
+ ApplyInverseTransforms(dec, dec->last_row_, num_rows, rows);
if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
// Nothing to output (this time).
} else {
@@ -1193,6 +1192,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
VP8LFillBitWindow(br);
dist_code = GetCopyDistance(dist_symbol, br);
dist = PlaneCodeToDistance(width, dist_code);
+
if (VP8LIsEndOfStream(br)) break;
if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
goto Error;
@@ -1553,7 +1553,7 @@ static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
const int cache_pixs = width * num_rows_to_process;
uint8_t* const dst = output + width * cur_row;
const uint32_t* const src = dec->argb_cache_;
- ApplyInverseTransforms(dec, num_rows_to_process, in);
+ ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in);
WebPExtractGreen(src, dst, cache_pixs);
AlphaApplyFilter(alph_dec,
cur_row, cur_row + num_rows_to_process, dst, width);
diff --git a/thirdparty/libwebp/src/dec/vp8li_dec.h b/thirdparty/libwebp/src/dec/vp8li_dec.h
index 0a4d613f99..72b2e86120 100644
--- a/thirdparty/libwebp/src/dec/vp8li_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8li_dec.h
@@ -37,7 +37,7 @@ struct VP8LTransform {
int bits_; // subsampling bits defining transform window.
int xsize_; // transform window X index.
int ysize_; // transform window Y index.
- uint32_t *data_; // transform data.
+ uint32_t* data_; // transform data.
};
typedef struct {
@@ -48,23 +48,23 @@ typedef struct {
int huffman_mask_;
int huffman_subsample_bits_;
int huffman_xsize_;
- uint32_t *huffman_image_;
+ uint32_t* huffman_image_;
int num_htree_groups_;
- HTreeGroup *htree_groups_;
- HuffmanCode *huffman_tables_;
+ HTreeGroup* htree_groups_;
+ HuffmanCode* huffman_tables_;
} VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder;
struct VP8LDecoder {
VP8StatusCode status_;
VP8LDecodeState state_;
- VP8Io *io_;
+ VP8Io* io_;
- const WebPDecBuffer *output_; // shortcut to io->opaque->output
+ const WebPDecBuffer* output_; // shortcut to io->opaque->output
- uint32_t *pixels_; // Internal data: either uint8_t* for alpha
+ uint32_t* pixels_; // Internal data: either uint8_t* for alpha
// or uint32_t* for BGRA.
- uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage.
+ uint32_t* argb_cache_; // Scratch buffer for temporary BGRA storage.
VP8LBitReader br_;
int incremental_; // if true, incremental decoding is expected
@@ -86,8 +86,8 @@ struct VP8LDecoder {
// or'd bitset storing the transforms types.
uint32_t transforms_seen_;
- uint8_t *rescaler_memory; // Working memory for rescaling work.
- WebPRescaler *rescaler; // Common rescaler for all channels.
+ uint8_t* rescaler_memory; // Working memory for rescaling work.
+ WebPRescaler* rescaler; // Common rescaler for all channels.
};
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/demux/demux.c b/thirdparty/libwebp/src/demux/demux.c
index ab6433e54b..1b3cc2e0a8 100644
--- a/thirdparty/libwebp/src/demux/demux.c
+++ b/thirdparty/libwebp/src/demux/demux.c
@@ -24,8 +24,8 @@
#include "src/webp/format_constants.h"
#define DMUX_MAJ_VERSION 1
-#define DMUX_MIN_VERSION 0
-#define DMUX_REV_VERSION 3
+#define DMUX_MIN_VERSION 1
+#define DMUX_REV_VERSION 0
typedef struct {
size_t start_; // start location of the data
diff --git a/thirdparty/libwebp/src/dsp/dec_neon.c b/thirdparty/libwebp/src/dsp/dec_neon.c
index ffa697fcf9..239ec4167e 100644
--- a/thirdparty/libwebp/src/dsp/dec_neon.c
+++ b/thirdparty/libwebp/src/dsp/dec_neon.c
@@ -1361,7 +1361,8 @@ static void RD4_NEON(uint8_t* dst) { // Down-right
const uint32_t J = dst[-1 + 1 * BPS];
const uint32_t K = dst[-1 + 2 * BPS];
const uint32_t L = dst[-1 + 3 * BPS];
- const uint64x1_t LKJI____ = vcreate_u64(L | (K << 8) | (J << 16) | (I << 24));
+ const uint64x1_t LKJI____ =
+ vcreate_u64((uint64_t)L | (K << 8) | (J << 16) | (I << 24));
const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC);
const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8));
const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16));
@@ -1427,10 +1428,16 @@ static WEBP_INLINE void DC8_NEON(uint8_t* dst, int do_top, int do_left) {
if (do_top) {
const uint8x8_t A = vld1_u8(dst - BPS); // top row
+#if defined(__aarch64__)
+ const uint16x8_t B = vmovl_u8(A);
+ const uint16_t p2 = vaddvq_u16(B);
+ sum_top = vdupq_n_u16(p2);
+#else
const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
const uint16x4_t p1 = vpadd_u16(p0, p0);
const uint16x4_t p2 = vpadd_u16(p1, p1);
sum_top = vcombine_u16(p2, p2);
+#endif
}
if (do_left) {
diff --git a/thirdparty/libwebp/src/dsp/dsp.h b/thirdparty/libwebp/src/dsp/dsp.h
index fafc2d05d3..a784de334a 100644
--- a/thirdparty/libwebp/src/dsp/dsp.h
+++ b/thirdparty/libwebp/src/dsp/dsp.h
@@ -246,9 +246,9 @@ extern VP8Fdct VP8FTransform2; // performs two transforms at a time
extern VP8WHT VP8FTransformWHT;
// Predictions
// *dst is the destination block. *top and *left can be NULL.
-typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left,
+typedef void (*VP8IntraPreds)(uint8_t* dst, const uint8_t* left,
const uint8_t* top);
-typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top);
+typedef void (*VP8Intra4Preds)(uint8_t* dst, const uint8_t* top);
extern VP8Intra4Preds VP8EncPredLuma4;
extern VP8IntraPreds VP8EncPredLuma16;
extern VP8IntraPreds VP8EncPredChroma8;
diff --git a/thirdparty/libwebp/src/dsp/lossless.c b/thirdparty/libwebp/src/dsp/lossless.c
index d05af84e7b..aad5f43ec9 100644
--- a/thirdparty/libwebp/src/dsp/lossless.c
+++ b/thirdparty/libwebp/src/dsp/lossless.c
@@ -81,7 +81,7 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
// gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is
// inlined.
-#if defined(__arm__) && LOCAL_GCC_VERSION <= 0x409
+#if defined(__arm__) && defined(__GNUC__) && LOCAL_GCC_VERSION <= 0x409
# define LOCAL_INLINE __attribute__ ((noinline))
#else
# define LOCAL_INLINE WEBP_INLINE
@@ -167,15 +167,20 @@ static uint32_t Predictor13_C(uint32_t left, const uint32_t* const top) {
return pred;
}
-GENERATE_PREDICTOR_ADD(Predictor0_C, PredictorAdd0_C)
+static void PredictorAdd0_C(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int x;
+ (void)upper;
+ for (x = 0; x < num_pixels; ++x) out[x] = VP8LAddPixels(in[x], ARGB_BLACK);
+}
static void PredictorAdd1_C(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) {
int i;
uint32_t left = out[-1];
+ (void)upper;
for (i = 0; i < num_pixels; ++i) {
out[i] = left = VP8LAddPixels(in[i], left);
}
- (void)upper;
}
GENERATE_PREDICTOR_ADD(Predictor2_C, PredictorAdd2_C)
GENERATE_PREDICTOR_ADD(Predictor3_C, PredictorAdd3_C)
diff --git a/thirdparty/libwebp/src/dsp/lossless_common.h b/thirdparty/libwebp/src/dsp/lossless_common.h
index a2648d1737..9c2ebe6809 100644
--- a/thirdparty/libwebp/src/dsp/lossless_common.h
+++ b/thirdparty/libwebp/src/dsp/lossless_common.h
@@ -177,6 +177,7 @@ uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \
int x; \
+ assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(out[x - 1], upper + x); \
out[x] = VP8LAddPixels(in[x], pred); \
@@ -189,6 +190,7 @@ static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
static void PREDICTOR_SUB(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \
int x; \
+ assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(in[x - 1], upper + x); \
out[x] = VP8LSubPixels(in[x], pred); \
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
index 8adc52139b..e676f6fdc9 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
@@ -455,8 +455,9 @@ static void PredictorSub0_SSE2(const uint32_t* in, const uint32_t* upper,
_mm_storeu_si128((__m128i*)&out[i], res);
}
if (i != num_pixels) {
- VP8LPredictorsSub_C[0](in + i, upper + i, num_pixels - i, out + i);
+ VP8LPredictorsSub_C[0](in + i, NULL, num_pixels - i, out + i);
}
+ (void)upper;
}
#define GENERATE_PREDICTOR_1(X, IN) \
diff --git a/thirdparty/libwebp/src/dsp/lossless_sse2.c b/thirdparty/libwebp/src/dsp/lossless_sse2.c
index 17d7576419..aef0cee1b3 100644
--- a/thirdparty/libwebp/src/dsp/lossless_sse2.c
+++ b/thirdparty/libwebp/src/dsp/lossless_sse2.c
@@ -191,8 +191,9 @@ static void PredictorAdd0_SSE2(const uint32_t* in, const uint32_t* upper,
_mm_storeu_si128((__m128i*)&out[i], res);
}
if (i != num_pixels) {
- VP8LPredictorsAdd_C[0](in + i, upper + i, num_pixels - i, out + i);
+ VP8LPredictorsAdd_C[0](in + i, NULL, num_pixels - i, out + i);
}
+ (void)upper;
}
// Predictor1: left.
diff --git a/thirdparty/libwebp/src/dsp/upsampling_msa.c b/thirdparty/libwebp/src/dsp/upsampling_msa.c
index 99eea70e7d..f2e03e85e9 100644
--- a/thirdparty/libwebp/src/dsp/upsampling_msa.c
+++ b/thirdparty/libwebp/src/dsp/upsampling_msa.c
@@ -576,9 +576,9 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \
const uint32_t l_uv = ((cur_u[0]) | ((cur_v[0]) << 16)); \
const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
const uint8_t* ptop_y = &top_y[1]; \
- uint8_t *ptop_dst = top_dst + XSTEP; \
+ uint8_t* ptop_dst = top_dst + XSTEP; \
const uint8_t* pbot_y = &bot_y[1]; \
- uint8_t *pbot_dst = bot_dst + XSTEP; \
+ uint8_t* pbot_dst = bot_dst + XSTEP; \
\
FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
if (bot_y != NULL) { \
diff --git a/thirdparty/libwebp/src/dsp/upsampling_neon.c b/thirdparty/libwebp/src/dsp/upsampling_neon.c
index 17cbc9f911..6ba71a7de5 100644
--- a/thirdparty/libwebp/src/dsp/upsampling_neon.c
+++ b/thirdparty/libwebp/src/dsp/upsampling_neon.c
@@ -58,8 +58,8 @@
} while (0)
// Turn the macro into a function for reducing code-size when non-critical
-static void Upsample16Pixels_NEON(const uint8_t *r1, const uint8_t *r2,
- uint8_t *out) {
+static void Upsample16Pixels_NEON(const uint8_t* r1, const uint8_t* r2,
+ uint8_t* out) {
UPSAMPLE_16PIXELS(r1, r2, out);
}
@@ -190,14 +190,14 @@ static const int16_t kCoeffs1[4] = { 19077, 26149, 6419, 13320 };
}
#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \
-static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \
- const uint8_t *top_u, const uint8_t *top_v, \
- const uint8_t *cur_u, const uint8_t *cur_v, \
- uint8_t *top_dst, uint8_t *bottom_dst, int len) { \
+static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
+ const uint8_t* top_u, const uint8_t* top_v, \
+ const uint8_t* cur_u, const uint8_t* cur_v, \
+ uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
int block; \
/* 16 byte aligned array to cache reconstructed u and v */ \
uint8_t uv_buf[2 * 32 + 15]; \
- uint8_t *const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
+ uint8_t* const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
const int uv_len = (len + 1) >> 1; \
/* 9 pixels must be read-able for each block */ \
const int num_blocks = (uv_len - 1) >> 3; \
diff --git a/thirdparty/libwebp/src/enc/histogram_enc.c b/thirdparty/libwebp/src/enc/histogram_enc.c
index d89b98524a..a4e6bf3a98 100644
--- a/thirdparty/libwebp/src/enc/histogram_enc.c
+++ b/thirdparty/libwebp/src/enc/histogram_enc.c
@@ -641,7 +641,7 @@ static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo,
// Merges some histograms with same bin_id together if it's advantageous.
// Sets the remaining histograms to NULL.
static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo,
- int *num_used,
+ int* num_used,
const uint16_t* const clusters,
uint16_t* const cluster_mappings,
VP8LHistogram* cur_combo,
diff --git a/thirdparty/libwebp/src/enc/picture_csp_enc.c b/thirdparty/libwebp/src/enc/picture_csp_enc.c
index 02d9df76d5..718e014ed2 100644
--- a/thirdparty/libwebp/src/enc/picture_csp_enc.c
+++ b/thirdparty/libwebp/src/enc/picture_csp_enc.c
@@ -29,11 +29,15 @@
#define USE_INVERSE_ALPHA_TABLE
#ifdef WORDS_BIGENDIAN
-#define ALPHA_OFFSET 0 // uint32_t 0xff000000 is 0xff,00,00,00 in memory
+// uint32_t 0xff000000 is 0xff,00,00,00 in memory
+#define CHANNEL_OFFSET(i) (i)
#else
-#define ALPHA_OFFSET 3 // uint32_t 0xff000000 is 0x00,00,00,ff in memory
+// uint32_t 0xff000000 is 0x00,00,00,ff in memory
+#define CHANNEL_OFFSET(i) (3-(i))
#endif
+#define ALPHA_OFFSET CHANNEL_OFFSET(0)
+
//------------------------------------------------------------------------------
// Detection of non-trivial transparency
@@ -997,10 +1001,10 @@ static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace,
return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
} else {
const uint8_t* const argb = (const uint8_t*)picture->argb;
- const uint8_t* const a = argb + (0 ^ ALPHA_OFFSET);
- const uint8_t* const r = argb + (1 ^ ALPHA_OFFSET);
- const uint8_t* const g = argb + (2 ^ ALPHA_OFFSET);
- const uint8_t* const b = argb + (3 ^ ALPHA_OFFSET);
+ const uint8_t* const a = argb + CHANNEL_OFFSET(0);
+ const uint8_t* const r = argb + CHANNEL_OFFSET(1);
+ const uint8_t* const g = argb + CHANNEL_OFFSET(2);
+ const uint8_t* const b = argb + CHANNEL_OFFSET(3);
picture->colorspace = WEBP_YUV420;
return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride,
@@ -1050,7 +1054,7 @@ int WebPPictureYUVAToARGB(WebPPicture* picture) {
const int height = picture->height;
const int argb_stride = 4 * picture->argb_stride;
uint8_t* dst = (uint8_t*)picture->argb;
- const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
+ const uint8_t* cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
WebPUpsampleLinePairFunc upsample =
WebPGetLinePairConverter(ALPHA_OFFSET > 0);
diff --git a/thirdparty/libwebp/src/enc/vp8i_enc.h b/thirdparty/libwebp/src/enc/vp8i_enc.h
index 24e1944610..fedcaeea27 100644
--- a/thirdparty/libwebp/src/enc/vp8i_enc.h
+++ b/thirdparty/libwebp/src/enc/vp8i_enc.h
@@ -31,8 +31,8 @@ extern "C" {
// version numbers
#define ENC_MAJ_VERSION 1
-#define ENC_MIN_VERSION 0
-#define ENC_REV_VERSION 3
+#define ENC_MIN_VERSION 1
+#define ENC_REV_VERSION 0
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
@@ -249,7 +249,7 @@ typedef struct {
int percent0_; // saved initial progress percent
DError left_derr_; // left error diffusion (u/v)
- DError *top_derr_; // top diffusion error - NULL if disabled
+ DError* top_derr_; // top diffusion error - NULL if disabled
uint8_t* y_left_; // left luma samples (addressable from index -1 to 15).
uint8_t* u_left_; // left u samples (addressable from index -1 to 7)
diff --git a/thirdparty/libwebp/src/mux/muxi.h b/thirdparty/libwebp/src/mux/muxi.h
index 7bc0b07e9b..ad3e1bdb97 100644
--- a/thirdparty/libwebp/src/mux/muxi.h
+++ b/thirdparty/libwebp/src/mux/muxi.h
@@ -28,8 +28,8 @@ extern "C" {
// Defines and constants.
#define MUX_MAJ_VERSION 1
-#define MUX_MIN_VERSION 0
-#define MUX_REV_VERSION 3
+#define MUX_MIN_VERSION 1
+#define MUX_REV_VERSION 0
// Chunk object.
typedef struct WebPChunk WebPChunk;
diff --git a/thirdparty/libwebp/src/mux/muxread.c b/thirdparty/libwebp/src/mux/muxread.c
index 268f6acb53..ae3b876bc5 100644
--- a/thirdparty/libwebp/src/mux/muxread.c
+++ b/thirdparty/libwebp/src/mux/muxread.c
@@ -100,7 +100,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
WebPMuxImage* const wpi) {
const uint8_t* bytes = chunk->data_.bytes;
size_t size = chunk->data_.size;
- const uint8_t* const last = bytes + size;
+ const uint8_t* const last = (bytes == NULL) ? NULL : bytes + size;
WebPChunk subchunk;
size_t subchunk_size;
WebPChunk** unknown_chunk_list = &wpi->unknown_;
diff --git a/thirdparty/libwebp/src/utils/color_cache_utils.h b/thirdparty/libwebp/src/utils/color_cache_utils.h
index ec21d5199b..b45d47c2d5 100644
--- a/thirdparty/libwebp/src/utils/color_cache_utils.h
+++ b/thirdparty/libwebp/src/utils/color_cache_utils.h
@@ -26,7 +26,7 @@ extern "C" {
// Main color cache struct.
typedef struct {
- uint32_t *colors_; // color entries
+ uint32_t* colors_; // color entries
int hash_shift_; // Hash shift: 32 - hash_bits_.
int hash_bits_;
} VP8LColorCache;
diff --git a/thirdparty/libwebp/src/utils/thread_utils.c b/thirdparty/libwebp/src/utils/thread_utils.c
index 438296b45f..4e470e17ac 100644
--- a/thirdparty/libwebp/src/utils/thread_utils.c
+++ b/thirdparty/libwebp/src/utils/thread_utils.c
@@ -73,7 +73,7 @@ typedef struct {
#endif
static int pthread_create(pthread_t* const thread, const void* attr,
- unsigned int (__stdcall *start)(void*), void* arg) {
+ unsigned int (__stdcall* start)(void*), void* arg) {
(void)attr;
#ifdef USE_CREATE_THREAD
*thread = CreateThread(NULL, /* lpThreadAttributes */
diff --git a/thirdparty/libwebp/src/utils/utils.c b/thirdparty/libwebp/src/utils/utils.c
index 44d5c14f01..764f752b82 100644
--- a/thirdparty/libwebp/src/utils/utils.c
+++ b/thirdparty/libwebp/src/utils/utils.c
@@ -216,9 +216,14 @@ void WebPSafeFree(void* const ptr) {
free(ptr);
}
-// Public API function.
+// Public API functions.
+
+void* WebPMalloc(size_t size) {
+ return WebPSafeMalloc(1, size);
+}
+
void WebPFree(void* ptr) {
- free(ptr);
+ WebPSafeFree(ptr);
}
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/webp/decode.h b/thirdparty/libwebp/src/webp/decode.h
index ae8bfe840e..80dd0ef0cc 100644
--- a/thirdparty/libwebp/src/webp/decode.h
+++ b/thirdparty/libwebp/src/webp/decode.h
@@ -20,7 +20,7 @@
extern "C" {
#endif
-#define WEBP_DECODER_ABI_VERSION 0x0208 // MAJOR(8b) + MINOR(8b)
+#define WEBP_DECODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b)
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
// the types are left here for reference.
@@ -91,9 +91,6 @@ WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
uint8_t** u, uint8_t** v,
int* stride, int* uv_stride);
-// Releases memory returned by the WebPDecode*() functions above.
-WEBP_EXTERN void WebPFree(void* ptr);
-
// These five functions are variants of the above ones, that decode the image
// directly into a pre-allocated buffer 'output_buffer'. The maximum storage
// available in this buffer is indicated by 'output_buffer_size'. If this
diff --git a/thirdparty/libwebp/src/webp/encode.h b/thirdparty/libwebp/src/webp/encode.h
index 339f8810aa..655166e7d4 100644
--- a/thirdparty/libwebp/src/webp/encode.h
+++ b/thirdparty/libwebp/src/webp/encode.h
@@ -20,7 +20,7 @@
extern "C" {
#endif
-#define WEBP_ENCODER_ABI_VERSION 0x020e // MAJOR(8b) + MINOR(8b)
+#define WEBP_ENCODER_ABI_VERSION 0x020f // MAJOR(8b) + MINOR(8b)
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
// the types are left here for reference.
@@ -79,9 +79,6 @@ WEBP_EXTERN size_t WebPEncodeLosslessBGRA(const uint8_t* bgra,
int width, int height, int stride,
uint8_t** output);
-// Releases memory returned by the WebPEncode*() functions above.
-WEBP_EXTERN void WebPFree(void* ptr);
-
//------------------------------------------------------------------------------
// Coding parameters
@@ -306,7 +303,7 @@ struct WebPPicture {
// YUV input (mostly used for input to lossy compression)
WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr).
int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION)
- uint8_t *y, *u, *v; // pointers to luma/chroma planes.
+ uint8_t* y, *u, *v; // pointers to luma/chroma planes.
int y_stride, uv_stride; // luma/chroma strides.
uint8_t* a; // pointer to the alpha plane
int a_stride; // stride of the alpha plane
@@ -350,7 +347,7 @@ struct WebPPicture {
uint32_t pad3[3]; // padding for later use
// Unused for now
- uint8_t *pad4, *pad5;
+ uint8_t* pad4, *pad5;
uint32_t pad6[8]; // padding for later use
// PRIVATE FIELDS
diff --git a/thirdparty/libwebp/src/webp/mux.h b/thirdparty/libwebp/src/webp/mux.h
index 66096a92e0..7d27489a40 100644
--- a/thirdparty/libwebp/src/webp/mux.h
+++ b/thirdparty/libwebp/src/webp/mux.h
@@ -57,7 +57,7 @@ extern "C" {
WebPMuxGetChunk(mux, "ICCP", &icc_profile);
// ... (Consume icc_data).
WebPMuxDelete(mux);
- free(data);
+ WebPFree(data);
*/
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
@@ -245,7 +245,7 @@ WEBP_EXTERN WebPMuxError WebPMuxPushFrame(
WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data);
// Gets the nth frame from the mux object.
-// The content of 'frame->bitstream' is allocated using malloc(), and NOT
+// The content of 'frame->bitstream' is allocated using WebPMalloc(), and NOT
// owned by the 'mux' object. It MUST be deallocated by the caller by calling
// WebPDataClear().
// nth=0 has a special meaning - last position.
@@ -376,10 +376,10 @@ WEBP_EXTERN WebPMuxError WebPMuxNumChunks(const WebPMux* mux,
// Assembles all chunks in WebP RIFF format and returns in 'assembled_data'.
// This function also validates the mux object.
// Note: The content of 'assembled_data' will be ignored and overwritten.
-// Also, the content of 'assembled_data' is allocated using malloc(), and NOT
-// owned by the 'mux' object. It MUST be deallocated by the caller by calling
-// WebPDataClear(). It's always safe to call WebPDataClear() upon return,
-// even in case of error.
+// Also, the content of 'assembled_data' is allocated using WebPMalloc(), and
+// NOT owned by the 'mux' object. It MUST be deallocated by the caller by
+// calling WebPDataClear(). It's always safe to call WebPDataClear() upon
+// return, even in case of error.
// Parameters:
// mux - (in/out) object whose chunks are to be assembled
// assembled_data - (out) assembled WebP data
diff --git a/thirdparty/libwebp/src/webp/mux_types.h b/thirdparty/libwebp/src/webp/mux_types.h
index ceea77dfc6..2fe8195839 100644
--- a/thirdparty/libwebp/src/webp/mux_types.h
+++ b/thirdparty/libwebp/src/webp/mux_types.h
@@ -14,7 +14,6 @@
#ifndef WEBP_WEBP_MUX_TYPES_H_
#define WEBP_WEBP_MUX_TYPES_H_
-#include <stdlib.h> // free()
#include <string.h> // memset()
#include "./types.h"
@@ -56,6 +55,7 @@ typedef enum WebPMuxAnimBlend {
// Data type used to describe 'raw' data, e.g., chunk data
// (ICC profile, metadata) and WebP compressed image data.
+// 'bytes' memory must be allocated using WebPMalloc() and such.
struct WebPData {
const uint8_t* bytes;
size_t size;
@@ -68,11 +68,11 @@ static WEBP_INLINE void WebPDataInit(WebPData* webp_data) {
}
}
-// Clears the contents of the 'webp_data' object by calling free(). Does not
-// deallocate the object itself.
+// Clears the contents of the 'webp_data' object by calling WebPFree().
+// Does not deallocate the object itself.
static WEBP_INLINE void WebPDataClear(WebPData* webp_data) {
if (webp_data != NULL) {
- free((void*)webp_data->bytes);
+ WebPFree((void*)webp_data->bytes);
WebPDataInit(webp_data);
}
}
@@ -83,7 +83,7 @@ static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {
if (src == NULL || dst == NULL) return 0;
WebPDataInit(dst);
if (src->bytes != NULL && src->size != 0) {
- dst->bytes = (uint8_t*)malloc(src->size);
+ dst->bytes = (uint8_t*)WebPMalloc(src->size);
if (dst->bytes == NULL) return 0;
memcpy((void*)dst->bytes, src->bytes, src->size);
dst->size = src->size;
diff --git a/thirdparty/libwebp/src/webp/types.h b/thirdparty/libwebp/src/webp/types.h
index 0ce2622e41..47f7f2b007 100644
--- a/thirdparty/libwebp/src/webp/types.h
+++ b/thirdparty/libwebp/src/webp/types.h
@@ -7,7 +7,7 @@
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
-// Common types
+// Common types + memory wrappers
//
// Author: Skal (pascal.massimino@gmail.com)
@@ -49,4 +49,20 @@ 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))
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Allocates 'size' bytes of memory. Returns NULL upon error. Memory
+// must be deallocated by calling WebPFree(). This function is made available
+// by the core 'libwebp' library.
+WEBP_EXTERN void* WebPMalloc(size_t size);
+
+// Releases memory returned by the WebPDecode*() functions (from decode.h).
+WEBP_EXTERN void WebPFree(void* ptr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // WEBP_WEBP_TYPES_H_