From fb832b482c6e74696271b70f484ae5184fb47f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 27 Jul 2024 21:19:10 +0200 Subject: [PATCH] Fix memory leak of non-RGBA image data, clear all image info The image data was not being freed when `IGraphics::LoadTextureRawMove` is used with images that are not in RGBA format as this falls back to using `IGraphics::LoadTextureRaw` which requires manually freeing the image data. Also consistently clear all image info in `LoadTextureRawMove`. This makes it necessary to store the size of the preview image in the editor separately, as previously the width and height of the unloaded image info were being used to render the preview image. --- src/engine/client/graphics_threaded.cpp | 5 ++++- src/game/client/components/menus_browser.cpp | 1 - src/game/editor/editor.cpp | 16 +++++++++------- src/game/editor/editor.h | 3 ++- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index 1e40d81a7..3f624be32 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -474,7 +474,9 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRawMove(CImageInfo &Ima if(Image.m_Format != CImageInfo::FORMAT_RGBA) { // Moving not possible, texture needs to be converted - return LoadTextureRaw(Image, Flags, pTexName); + IGraphics::CTextureHandle TextureHandle = LoadTextureRaw(Image, Flags, pTexName); + Image.Free(); + return TextureHandle; } LoadTextureAddWarning(Image.m_Width, Image.m_Height, Flags, pTexName, m_vWarnings); @@ -486,6 +488,7 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRawMove(CImageInfo &Ima CCommandBuffer::SCommand_Texture_Create Cmd = LoadTextureCreateCommand(TextureHandle.Id(), Image.m_Width, Image.m_Height, Flags); Cmd.m_pData = Image.m_pData; Image.m_pData = nullptr; + Image.Free(); AddCmd(Cmd); return TextureHandle; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 3bbb9f2fc..a3d6898a6 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -2001,7 +2001,6 @@ void CMenus::LoadCommunityIconFinish(const char *pCommunityId, CImageInfo &Info, pData[i * Step + 2] = v; } CommunityIcon.m_GreyTexture = Graphics()->LoadTextureRawMove(Info, 0, pCommunityId); - Info.m_pData = nullptr; auto ExistingIcon = std::find_if(m_vCommunityIcons.begin(), m_vCommunityIcons.end(), [pCommunityId](const SCommunityIcon &Element) { return str_comp(Element.m_aCommunityId, pCommunityId) == 0; diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index f04d73f08..8aabc4f20 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -5140,11 +5140,13 @@ void CEditor::RenderFileDialog() { char aBuffer[IO_MAX_PATH_LENGTH]; str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_pFileDialogPath, m_vpFilteredFileList[m_FilesSelectedIndex]->m_aFilename); - if(Graphics()->LoadPng(m_FilePreviewImageInfo, aBuffer, m_vpFilteredFileList[m_FilesSelectedIndex]->m_StorageType)) + CImageInfo PreviewImageInfo; + if(Graphics()->LoadPng(PreviewImageInfo, aBuffer, m_vpFilteredFileList[m_FilesSelectedIndex]->m_StorageType)) { Graphics()->UnloadTexture(&m_FilePreviewImage); - m_FilePreviewImage = Graphics()->LoadTextureRawMove(m_FilePreviewImageInfo, 0, aBuffer); - m_FilePreviewImageInfo.m_pData = nullptr; + m_FilePreviewImageWidth = PreviewImageInfo.m_Width; + m_FilePreviewImageHeight = PreviewImageInfo.m_Height; + m_FilePreviewImage = Graphics()->LoadTextureRawMove(PreviewImageInfo, 0, aBuffer); m_FilePreviewState = PREVIEW_LOADED; } else @@ -5167,11 +5169,11 @@ void CEditor::RenderFileDialog() Preview.Margin(10.0f, &Preview); if(m_FilePreviewState == PREVIEW_LOADED) { - int w = m_FilePreviewImageInfo.m_Width; - int h = m_FilePreviewImageInfo.m_Height; - if(m_FilePreviewImageInfo.m_Width > Preview.w) + int w = m_FilePreviewImageWidth; + int h = m_FilePreviewImageHeight; + if(m_FilePreviewImageWidth > Preview.w) { - h = m_FilePreviewImageInfo.m_Height * Preview.w / m_FilePreviewImageInfo.m_Width; + h = m_FilePreviewImageHeight * Preview.w / m_FilePreviewImageWidth; w = Preview.w; } if(h > Preview.h) diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 151fa36ea..bead2c217 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -610,7 +610,8 @@ public: IGraphics::CTextureHandle m_FilePreviewImage; int m_FilePreviewSound; EPreviewState m_FilePreviewState; - CImageInfo m_FilePreviewImageInfo; + int m_FilePreviewImageWidth; + int m_FilePreviewImageHeight; bool m_FileDialogOpening; int m_ToolbarPreviewSound;