summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/error/error_macros.cpp4
-rw-r--r--core/error/error_macros.h3
-rw-r--r--core/io/file_access_network.cpp1
-rw-r--r--core/io/image.cpp130
-rw-r--r--core/io/image.h2
-rw-r--r--core/math/expression.cpp4
-rw-r--r--core/templates/rid_owner.h56
7 files changed, 158 insertions, 42 deletions
diff --git a/core/error/error_macros.cpp b/core/error/error_macros.cpp
index 928ddd3397..ceccd43259 100644
--- a/core/error/error_macros.cpp
+++ b/core/error/error_macros.cpp
@@ -118,3 +118,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify, bool p_fatal) {
_err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), p_fatal);
}
+
+void _err_flush_stdout() {
+ fflush(stdout);
+}
diff --git a/core/error/error_macros.h b/core/error/error_macros.h
index 802d7f9ef4..7b032fb4cd 100644
--- a/core/error/error_macros.h
+++ b/core/error/error_macros.h
@@ -69,6 +69,7 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool p_editor_notify = false, bool fatal = false);
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool fatal = false);
+void _err_flush_stdout();
#ifdef __GNUC__
//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
@@ -789,6 +790,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
#define CRASH_NOW() \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed."); \
+ _err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
((void)0)
@@ -801,6 +803,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
#define CRASH_NOW_MSG(m_msg) \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", m_msg); \
+ _err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
((void)0)
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 307004b1c2..cb38ac0928 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -487,7 +487,6 @@ FileAccessNetwork::~FileAccessNetwork() {
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex();
- id = nc->last_id++;
nc->accesses.erase(id);
nc->unlock_mutex();
}
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 4f72599faf..577fc59807 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -30,14 +30,17 @@
#include "image.h"
+#include "core/error/error_list.h"
#include "core/error/error_macros.h"
#include "core/io/image_loader.h"
#include "core/io/resource_loader.h"
#include "core/math/math_funcs.h"
#include "core/string/print_string.h"
#include "core/templates/hash_map.h"
+#include "core/variant/dictionary.h"
#include <stdio.h>
+#include <cmath>
const char *Image::format_names[Image::FORMAT_MAX] = {
"Lum8", //luminance
@@ -3135,6 +3138,8 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("rgbe_to_srgb"), &Image::rgbe_to_srgb);
ClassDB::bind_method(D_METHOD("bump_map_to_normal_map", "bump_scale"), &Image::bump_map_to_normal_map, DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("compute_image_metrics", "compared_image", "use_luma"), &Image::compute_image_metrics);
+
ClassDB::bind_method(D_METHOD("blit_rect", "src", "src_rect", "dst"), &Image::blit_rect);
ClassDB::bind_method(D_METHOD("blit_rect_mask", "src", "mask", "src_rect", "dst"), &Image::blit_rect_mask);
ClassDB::bind_method(D_METHOD("blend_rect", "src", "src_rect", "dst"), &Image::blend_rect);
@@ -3620,3 +3625,128 @@ Ref<Resource> Image::duplicate(bool p_subresources) const {
void Image::set_as_black() {
memset(data.ptrw(), 0, data.size());
}
+
+Dictionary Image::compute_image_metrics(const Ref<Image> p_compared_image, bool p_luma_metric) {
+ // https://github.com/richgel999/bc7enc_rdo/blob/master/LICENSE
+ //
+ // This is free and unencumbered software released into the public domain.
+ // Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+ // software, either in source code form or as a compiled binary, for any purpose,
+ // commercial or non - commercial, and by any means.
+ // In jurisdictions that recognize copyright laws, the author or authors of this
+ // software dedicate any and all copyright interest in the software to the public
+ // domain. We make this dedication for the benefit of the public at large and to
+ // the detriment of our heirs and successors. We intend this dedication to be an
+ // overt act of relinquishment in perpetuity of all present and future rights to
+ // this software under copyright law.
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
+ // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Dictionary result;
+ result["max"] = INFINITY;
+ result["mean"] = INFINITY;
+ result["mean_squared"] = INFINITY;
+ result["root_mean_squared"] = INFINITY;
+ result["peak_snr"] = 0.0f;
+
+ ERR_FAIL_NULL_V(p_compared_image, result);
+ Error err = OK;
+ Ref<Image> compared_image = duplicate(true);
+ if (compared_image->is_compressed()) {
+ err = compared_image->decompress();
+ }
+ ERR_FAIL_COND_V(err != OK, result);
+ Ref<Image> source_image = p_compared_image->duplicate(true);
+ if (source_image->is_compressed()) {
+ err = source_image->decompress();
+ }
+ ERR_FAIL_COND_V(err != OK, result);
+
+ ERR_FAIL_COND_V(err != OK, result);
+
+ ERR_FAIL_COND_V_MSG((compared_image->get_format() >= Image::FORMAT_RH) && (compared_image->get_format() <= Image::FORMAT_RGBE9995), result, "Metrics on HDR images are not supported.");
+ ERR_FAIL_COND_V_MSG((source_image->get_format() >= Image::FORMAT_RH) && (source_image->get_format() <= Image::FORMAT_RGBE9995), result, "Metrics on HDR images are not supported.");
+
+ double image_metric_max, image_metric_mean, image_metric_mean_squared, image_metric_root_mean_squared, image_metric_peak_snr = 0.0;
+ const bool average_component_error = true;
+
+ const uint32_t width = MIN(compared_image->get_width(), source_image->get_width());
+ const uint32_t height = MIN(compared_image->get_height(), source_image->get_height());
+
+ // Histogram approach originally due to Charles Bloom.
+ double hist[256];
+ memset(hist, 0, sizeof(hist));
+
+ for (uint32_t y = 0; y < height; y++) {
+ for (uint32_t x = 0; x < width; x++) {
+ const Color color_a = compared_image->get_pixel(x, y);
+
+ const Color color_b = source_image->get_pixel(x, y);
+
+ if (!p_luma_metric) {
+ ERR_FAIL_COND_V_MSG(color_a.r > 1.0f, Dictionary(), "Can't compare HDR colors.");
+ ERR_FAIL_COND_V_MSG(color_b.r > 1.0f, Dictionary(), "Can't compare HDR colors.");
+ hist[Math::abs(color_a.get_r8() - color_b.get_r8())]++;
+ ERR_FAIL_COND_V_MSG(color_a.g > 1.0f, Dictionary(), "Can't compare HDR colors.");
+ ERR_FAIL_COND_V_MSG(color_b.g > 1.0f, Dictionary(), "Can't compare HDR colors.");
+ hist[Math::abs(color_a.get_g8() - color_b.get_g8())]++;
+ ERR_FAIL_COND_V_MSG(color_a.b > 1.0f, Dictionary(), "Can't compare HDR colors.");
+ ERR_FAIL_COND_V_MSG(color_b.b > 1.0f, Dictionary(), "Can't compare HDR colors.");
+ hist[Math::abs(color_a.get_b8() - color_b.get_b8())]++;
+ ERR_FAIL_COND_V_MSG(color_a.a > 1.0f, Dictionary(), "Can't compare HDR colors.");
+ ERR_FAIL_COND_V_MSG(color_b.a > 1.0f, Dictionary(), "Can't compare HDR colors.");
+ hist[Math::abs(color_a.get_a8() - color_b.get_a8())]++;
+ } else {
+ ERR_FAIL_COND_V_MSG(color_a.r > 1.0f, Dictionary(), "Can't compare HDR colors.");
+ ERR_FAIL_COND_V_MSG(color_b.r > 1.0f, Dictionary(), "Can't compare HDR colors.");
+ // REC709 weightings
+ int luma_a = (13938U * color_a.get_r8() + 46869U * color_a.get_g8() + 4729U * color_a.get_b8() + 32768U) >> 16U;
+ int luma_b = (13938U * color_b.get_r8() + 46869U * color_b.get_g8() + 4729U * color_b.get_b8() + 32768U) >> 16U;
+ hist[Math::abs(luma_a - luma_b)]++;
+ }
+ }
+ }
+
+ image_metric_max = 0;
+ double sum = 0.0f, sum2 = 0.0f;
+ for (uint32_t i = 0; i < 256; i++) {
+ if (!hist[i]) {
+ continue;
+ }
+
+ image_metric_max = MAX(image_metric_max, i);
+
+ double x = i * hist[i];
+
+ sum += x;
+ sum2 += i * x;
+ }
+
+ // See http://richg42.blogspot.com/2016/09/how-to-compute-psnr-from-old-berkeley.html
+ double total_values = width * height;
+
+ if (average_component_error) {
+ total_values *= 4;
+ }
+
+ image_metric_mean = CLAMP(sum / total_values, 0.0f, 255.0f);
+ image_metric_mean_squared = CLAMP(sum2 / total_values, 0.0f, 255.0f * 255.0f);
+
+ image_metric_root_mean_squared = sqrt(image_metric_mean_squared);
+
+ if (!image_metric_root_mean_squared) {
+ image_metric_peak_snr = 1e+10f;
+ } else {
+ image_metric_peak_snr = CLAMP(log10(255.0f / image_metric_root_mean_squared) * 20.0f, 0.0f, 500.0f);
+ }
+ result["max"] = image_metric_max;
+ result["mean"] = image_metric_mean;
+ result["mean_squared"] = image_metric_mean_squared;
+ result["root_mean_squared"] = image_metric_root_mean_squared;
+ result["peak_snr"] = image_metric_peak_snr;
+ return result;
+}
diff --git a/core/io/image.h b/core/io/image.h
index ddfb2bb01d..53bfa0881f 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -399,6 +399,8 @@ public:
mipmaps = p_image->mipmaps;
data = p_image->data;
}
+
+ Dictionary compute_image_metrics(const Ref<Image> p_compared_image, bool p_luma_metric = true);
};
VARIANT_ENUM_CAST(Image::Format)
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index b447d09887..0ddac9744e 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -361,6 +361,7 @@ Error Expression::_get_token(Token &r_token) {
is_float = true;
} else if (c == 'e') {
reading = READING_EXP;
+ is_float = true;
} else {
reading = READING_DONE;
}
@@ -397,9 +398,6 @@ Error Expression::_get_token(Token &r_token) {
exp_beg = true;
} else if ((c == '-' || c == '+') && !exp_sign && !exp_beg) {
- if (c == '-') {
- is_float = true;
- }
exp_sign = true;
} else {
diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h
index 3ed81e76fd..95632cdec2 100644
--- a/core/templates/rid_owner.h
+++ b/core/templates/rid_owner.h
@@ -292,43 +292,32 @@ public:
_FORCE_INLINE_ uint32_t get_rid_count() const {
return alloc_count;
}
-
- _FORCE_INLINE_ T *get_ptr_by_index(uint32_t p_index) {
- ERR_FAIL_UNSIGNED_INDEX_V(p_index, alloc_count, nullptr);
+ void get_owned_list(List<RID> *p_owned) {
if (THREAD_SAFE) {
spin_lock.lock();
}
- uint64_t idx = free_list_chunks[p_index / elements_in_chunk][p_index % elements_in_chunk];
- T *ptr = &chunks[idx / elements_in_chunk][idx % elements_in_chunk];
- if (THREAD_SAFE) {
- spin_lock.unlock();
- }
- return ptr;
- }
-
- _FORCE_INLINE_ RID get_rid_by_index(uint32_t p_index) {
- ERR_FAIL_INDEX_V(p_index, alloc_count, RID());
- if (THREAD_SAFE) {
- spin_lock.lock();
+ for (size_t i = 0; i < max_alloc; i++) {
+ uint64_t validator = validator_chunks[i / elements_in_chunk][i % elements_in_chunk];
+ if (validator != 0xFFFFFFFF) {
+ p_owned->push_back(_make_from_id((validator << 32) | i));
+ }
}
- uint64_t idx = free_list_chunks[p_index / elements_in_chunk][p_index % elements_in_chunk];
- uint64_t validator = validator_chunks[idx / elements_in_chunk][idx % elements_in_chunk];
-
- RID rid = _make_from_id((validator << 32) | idx);
if (THREAD_SAFE) {
spin_lock.unlock();
}
- return rid;
}
- void get_owned_list(List<RID> *p_owned) {
+ //used for fast iteration in the elements or RIDs
+ void fill_owned_buffer(RID *p_rid_buffer) {
if (THREAD_SAFE) {
spin_lock.lock();
}
+ uint32_t idx = 0;
for (size_t i = 0; i < max_alloc; i++) {
uint64_t validator = validator_chunks[i / elements_in_chunk][i % elements_in_chunk];
if (validator != 0xFFFFFFFF) {
- p_owned->push_back(_make_from_id((validator << 32) | i));
+ p_rid_buffer[idx] = _make_from_id((validator << 32) | i);
+ idx++;
}
}
if (THREAD_SAFE) {
@@ -425,18 +414,14 @@ public:
return alloc.get_rid_count();
}
- _FORCE_INLINE_ RID get_rid_by_index(uint32_t p_index) {
- return alloc.get_rid_by_index(p_index);
- }
-
- _FORCE_INLINE_ T *get_ptr_by_index(uint32_t p_index) {
- return *alloc.get_ptr_by_index(p_index);
- }
-
_FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) {
return alloc.get_owned_list(p_owned);
}
+ void fill_owned_buffer(RID *p_rid_buffer) {
+ alloc.fill_owned_buffer(p_rid_buffer);
+ }
+
void set_description(const char *p_descrption) {
alloc.set_description(p_descrption);
}
@@ -485,17 +470,12 @@ public:
return alloc.get_rid_count();
}
- _FORCE_INLINE_ RID get_rid_by_index(uint32_t p_index) {
- return alloc.get_rid_by_index(p_index);
- }
-
- _FORCE_INLINE_ T *get_ptr_by_index(uint32_t p_index) {
- return alloc.get_ptr_by_index(p_index);
- }
-
_FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) {
return alloc.get_owned_list(p_owned);
}
+ void fill_owned_buffer(RID *p_rid_buffer) {
+ alloc.fill_owned_buffer(p_rid_buffer);
+ }
void set_description(const char *p_descrption) {
alloc.set_description(p_descrption);