diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index e0b2506c51e..24660ed52fd 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -15,7 +15,8 @@ 1. [A32NX/CAMERA] Improved default camera position for Virtual Reality (VR) - @aguther (Andreas Guther) 1. [A380X/EFB] Fixed doors automatically opening in flight - @saschl (saschl) 1. [A380X/FMS] Fixed layouting issue on FMS/ACTIVE/PERF/T.O page for some users - @flogross89 (floridude) -1. [A380X/TELEX] Added popup for telex consent @saschl (saschl) @Maximilian-Reuter (\_chaoz) +1. [A380X/TELEX] Added popup for telex consent - @saschl (saschl) @Maximilian-Reuter (\_chaoz) +1. [ND] Fix memory leak when using TERR ON ND - @Nufflee (nufflee) ## 0.12.0 diff --git a/fbw-common/src/wasm/terronnd/build.sh b/fbw-common/src/wasm/terronnd/build.sh index 54c5fb48ce2..15eead05952 100755 --- a/fbw-common/src/wasm/terronnd/build.sh +++ b/fbw-common/src/wasm/terronnd/build.sh @@ -62,6 +62,7 @@ clang++ \ -O2 \ -I "${MSFS_SDK}/WASM/include" \ -I "${MSFS_SDK}/SimConnect SDK/include" \ + -I "${DIR}/../cpp-msfs-framework/lib/" \ "${DIR}/src/main.cpp" \ "${DIR}/src/nanovg/nanovg.cpp" \ "${DIR}/src/navigationdisplay/collection.cpp" \ diff --git a/fbw-common/src/wasm/terronnd/src/navigationdisplay/display.h b/fbw-common/src/wasm/terronnd/src/navigationdisplay/display.h index 8896b6fae06..e1b8f67b131 100644 --- a/fbw-common/src/wasm/terronnd/src/navigationdisplay/display.h +++ b/fbw-common/src/wasm/terronnd/src/navigationdisplay/display.h @@ -6,13 +6,16 @@ #pragma clang diagnostic ignored "-Wsign-conversion" #include #include +#include #pragma clang diagnostic pop #include #include #include - #include +#define FMT_HEADER_ONLY +#include + #include "../simconnect/clientdataarea.hpp" #include "../simconnect/connection.hpp" #include "../simconnect/lvarobject.hpp" @@ -113,14 +116,38 @@ class Display : public DisplayBase { this->_frameData->defineArea(side == DisplaySide::Left ? FrameDataLeftName : FrameDataRightName); this->_frameData->requestArea(SIMCONNECT_CLIENT_DATA_PERIOD_ON_SET); this->_frameData->setOnChangeCallback([=]() { - this->destroyImage(); - if (!this->_ignoreNextFrame && this->_configuration.terrainActive) { - this->_nanovgImage = - nvgCreateImageMem(this->_context, 0, this->_frameData->data().data(), static_cast(this->_frameBufferSize)); if (this->_nanovgImage == 0) { - std::cerr << "TERR ON ND: Unable to decode the image from the stream" << std::endl; + // If we don't have an image yet, create one + this->_nanovgImage = nvgCreateImageMem(this->_context, 0, this->_frameData->data().data(), static_cast(this->_frameBufferSize)); + if (this->_nanovgImage == 0) { + std::cerr << fmt::format("TERR ON ND: Unable to create the image from the stream. Reason: {}", stbi_failure_reason()); + } + + return; + } + + // Otherwise, decode the PNG manually and update the existing image + int decodedWidth, decodedHeight; + uint8_t* decodedImage = stbi_load_from_memory(this->_frameData->data().data(), static_cast(this->_frameBufferSize), &decodedWidth, &decodedHeight, nullptr, 4); + if (decodedImage == nullptr) { + std::cerr << fmt::format("TERR ON ND: Unable to create the image from the stream. Reason: {}", stbi_failure_reason()); + return; + } + + int width, height; + nvgImageSize(this->_context, this->_nanovgImage, &width, &height); + + if (decodedWidth != width || decodedHeight != height) { + // This should never happen, but bail just in case + std::cerr << fmt::format("TERR ON ND: The image size does not match the expected size. Expected: {}x{}, actual: {}x{}", width, height, decodedWidth, decodedHeight); + stbi_image_free(decodedImage); + return; } + + nvgUpdateImage(this->_context, this->_nanovgImage, decodedImage); + + stbi_image_free(decodedImage); } else { this->resetNavigationDisplayData(); }