Merge pull request #7757 from Robyt3/Graphics-LoadTexture-Move

Avoid copying texture memory when possible
This commit is contained in:
Dennis Felsing 2024-01-04 11:32:42 +00:00 committed by GitHub
commit ca9c4f532a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 58 additions and 36 deletions

View file

@ -290,10 +290,7 @@ void CGraphics_Threaded::FreeTextureIndex(CTextureHandle *pIndex)
int CGraphics_Threaded::UnloadTexture(CTextureHandle *pIndex) int CGraphics_Threaded::UnloadTexture(CTextureHandle *pIndex)
{ {
if(pIndex->Id() == m_NullTexture.Id()) if(pIndex->IsNullTexture() || !pIndex->IsValid())
return 0;
if(!pIndex->IsValid())
return 0; return 0;
CCommandBuffer::SCommand_Texture_Destroy Cmd; CCommandBuffer::SCommand_Texture_Destroy Cmd;
@ -416,7 +413,7 @@ bool CGraphics_Threaded::IsSpriteTextureFullyTransparent(CImageInfo &FromImageIn
return IsImageSubFullyTransparent(FromImageInfo, x, y, w, h); return IsImageSubFullyTransparent(FromImageInfo, x, y, w, h);
} }
IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(size_t Width, size_t Height, CImageInfo::EImageFormat Format, const void *pData, int Flags, const char *pTexName) static void LoadTextureAddWarning(size_t Width, size_t Height, int Flags, const char *pTexName, std::vector<SWarning> &vWarnings)
{ {
if((Flags & IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE) != 0 || (Flags & IGraphics::TEXLOAD_TO_3D_TEXTURE) != 0) if((Flags & IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE) != 0 || (Flags & IGraphics::TEXLOAD_TO_3D_TEXTURE) != 0)
{ {
@ -424,30 +421,22 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(size_t Width, size_
{ {
SWarning NewWarning; SWarning NewWarning;
char aText[128]; char aText[128];
aText[0] = '\0'; str_format(aText, sizeof(aText), "\"%s\"", pTexName ? pTexName : "(no name)");
if(pTexName)
{
str_format(aText, sizeof(aText), "\"%s\"", pTexName);
}
str_format(NewWarning.m_aWarningMsg, sizeof(NewWarning.m_aWarningMsg), Localize("The width of texture %s is not divisible by %d, or the height is not divisible by %d, which might cause visual bugs."), aText, 16, 16); str_format(NewWarning.m_aWarningMsg, sizeof(NewWarning.m_aWarningMsg), Localize("The width of texture %s is not divisible by %d, or the height is not divisible by %d, which might cause visual bugs."), aText, 16, 16);
vWarnings.emplace_back(NewWarning);
m_vWarnings.emplace_back(NewWarning);
} }
} }
}
if(Width == 0 || Height == 0) static CCommandBuffer::SCommand_Texture_Create LoadTextureCreateCommand(int TextureId, size_t Width, size_t Height, int Flags)
return IGraphics::CTextureHandle(); {
IGraphics::CTextureHandle TextureHandle = FindFreeTextureIndex();
CCommandBuffer::SCommand_Texture_Create Cmd; CCommandBuffer::SCommand_Texture_Create Cmd;
Cmd.m_Slot = TextureHandle.Id(); Cmd.m_Slot = TextureId;
Cmd.m_Width = Width; Cmd.m_Width = Width;
Cmd.m_Height = Height; Cmd.m_Height = Height;
Cmd.m_Format = CCommandBuffer::TEXFORMAT_RGBA; Cmd.m_Format = CCommandBuffer::TEXFORMAT_RGBA;
Cmd.m_StoreFormat = CCommandBuffer::TEXFORMAT_RGBA; Cmd.m_StoreFormat = CCommandBuffer::TEXFORMAT_RGBA;
// flags
Cmd.m_Flags = 0; Cmd.m_Flags = 0;
if(Flags & IGraphics::TEXLOAD_NOMIPMAPS) if(Flags & IGraphics::TEXLOAD_NOMIPMAPS)
Cmd.m_Flags |= CCommandBuffer::TEXFLAG_NOMIPMAPS; Cmd.m_Flags |= CCommandBuffer::TEXFLAG_NOMIPMAPS;
@ -458,14 +447,51 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(size_t Width, size_
if((Flags & IGraphics::TEXLOAD_NO_2D_TEXTURE) != 0) if((Flags & IGraphics::TEXLOAD_NO_2D_TEXTURE) != 0)
Cmd.m_Flags |= CCommandBuffer::TEXFLAG_NO_2D_TEXTURE; Cmd.m_Flags |= CCommandBuffer::TEXFLAG_NO_2D_TEXTURE;
// copy texture data return Cmd;
}
IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(size_t Width, size_t Height, CImageInfo::EImageFormat Format, const void *pData, int Flags, const char *pTexName)
{
LoadTextureAddWarning(Width, Height, Flags, pTexName, m_vWarnings);
if(Width == 0 || Height == 0)
return IGraphics::CTextureHandle();
IGraphics::CTextureHandle TextureHandle = FindFreeTextureIndex();
CCommandBuffer::SCommand_Texture_Create Cmd = LoadTextureCreateCommand(TextureHandle.Id(), Width, Height, Flags);
// Copy texture data and convert if necessary
const size_t MemSize = Width * Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA); const size_t MemSize = Width * Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA);
void *pTmpData = malloc(MemSize); void *pTmpData = malloc(MemSize);
if(!ConvertToRGBA((uint8_t *)pTmpData, (const uint8_t *)pData, Width, Height, Format)) if(!ConvertToRGBA(static_cast<uint8_t *>(pTmpData), static_cast<const uint8_t *>(pData), Width, Height, Format))
{ {
dbg_msg("graphics", "converted image %s to RGBA, consider making its file format RGBA", pTexName ? pTexName : "(no name)"); dbg_msg("graphics", "converted image '%s' to RGBA, consider making its file format RGBA", pTexName ? pTexName : "(no name)");
} }
Cmd.m_pData = pTmpData; Cmd.m_pData = pTmpData;
AddCmd(Cmd);
return TextureHandle;
}
IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRawMove(size_t Width, size_t Height, CImageInfo::EImageFormat Format, void *pData, int Flags, const char *pTexName)
{
if(Format != CImageInfo::FORMAT_RGBA)
{
// Moving not possible, texture needs to be converted
return LoadTextureRaw(Width, Height, Format, pData, Flags, pTexName);
}
LoadTextureAddWarning(Width, Height, Flags, pTexName, m_vWarnings);
if(Width == 0 || Height == 0)
return IGraphics::CTextureHandle();
IGraphics::CTextureHandle TextureHandle = FindFreeTextureIndex();
CCommandBuffer::SCommand_Texture_Create Cmd = LoadTextureCreateCommand(TextureHandle.Id(), Width, Height, Flags);
Cmd.m_pData = pData;
AddCmd(Cmd); AddCmd(Cmd);
return TextureHandle; return TextureHandle;
@ -479,8 +505,7 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTexture(const char *pFilename,
CImageInfo Img; CImageInfo Img;
if(LoadPNG(&Img, pFilename, StorageType)) if(LoadPNG(&Img, pFilename, StorageType))
{ {
CTextureHandle ID = LoadTextureRaw(Img.m_Width, Img.m_Height, Img.m_Format, Img.m_pData, Flags, pFilename); CTextureHandle ID = LoadTextureRawMove(Img.m_Width, Img.m_Height, Img.m_Format, Img.m_pData, Flags, pFilename);
FreePNG(&Img);
if(ID.IsValid()) if(ID.IsValid())
{ {
if(g_Config.m_Debug) if(g_Config.m_Debug)

View file

@ -951,6 +951,7 @@ public:
void FreeTextureIndex(CTextureHandle *pIndex); void FreeTextureIndex(CTextureHandle *pIndex);
int UnloadTexture(IGraphics::CTextureHandle *pIndex) override; int UnloadTexture(IGraphics::CTextureHandle *pIndex) override;
IGraphics::CTextureHandle LoadTextureRaw(size_t Width, size_t Height, CImageInfo::EImageFormat Format, const void *pData, int Flags, const char *pTexName = nullptr) override; IGraphics::CTextureHandle LoadTextureRaw(size_t Width, size_t Height, CImageInfo::EImageFormat Format, const void *pData, int Flags, const char *pTexName = nullptr) override;
IGraphics::CTextureHandle LoadTextureRawMove(size_t Width, size_t Height, CImageInfo::EImageFormat Format, void *pData, int Flags, const char *pTexName = nullptr) override;
int LoadTextureRawSub(IGraphics::CTextureHandle TextureID, int x, int y, size_t Width, size_t Height, CImageInfo::EImageFormat Format, const void *pData) override; int LoadTextureRawSub(IGraphics::CTextureHandle TextureID, int x, int y, size_t Width, size_t Height, CImageInfo::EImageFormat Format, const void *pData) override;
IGraphics::CTextureHandle NullTexture() const override; IGraphics::CTextureHandle NullTexture() const override;

View file

@ -335,6 +335,7 @@ public:
virtual int UnloadTexture(CTextureHandle *pIndex) = 0; virtual int UnloadTexture(CTextureHandle *pIndex) = 0;
virtual CTextureHandle LoadTextureRaw(size_t Width, size_t Height, CImageInfo::EImageFormat Format, const void *pData, int Flags, const char *pTexName = nullptr) = 0; virtual CTextureHandle LoadTextureRaw(size_t Width, size_t Height, CImageInfo::EImageFormat Format, const void *pData, int Flags, const char *pTexName = nullptr) = 0;
virtual CTextureHandle LoadTextureRawMove(size_t Width, size_t Height, CImageInfo::EImageFormat Format, void *pData, int Flags, const char *pTexName = nullptr) = 0;
virtual int LoadTextureRawSub(CTextureHandle TextureID, int x, int y, size_t Width, size_t Height, CImageInfo::EImageFormat Format, const void *pData) = 0; virtual int LoadTextureRawSub(CTextureHandle TextureID, int x, int y, size_t Width, size_t Height, CImageInfo::EImageFormat Format, const void *pData) = 0;
virtual CTextureHandle LoadTexture(const char *pFilename, int StorageType, int Flags = 0) = 0; virtual CTextureHandle LoadTexture(const char *pFilename, int StorageType, int Flags = 0) = 0;
virtual CTextureHandle NullTexture() const = 0; virtual CTextureHandle NullTexture() const = 0;

View file

@ -75,8 +75,7 @@ void CCountryFlags::LoadCountryflagsIndexfile()
CCountryFlag CountryFlag; CCountryFlag CountryFlag;
CountryFlag.m_CountryCode = CountryCode; CountryFlag.m_CountryCode = CountryCode;
str_copy(CountryFlag.m_aCountryCodeString, aOrigin); str_copy(CountryFlag.m_aCountryCodeString, aOrigin);
CountryFlag.m_Texture = Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, 0, aOrigin); CountryFlag.m_Texture = Graphics()->LoadTextureRawMove(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, 0, aOrigin);
Graphics()->FreePNG(&Info);
if(g_Config.m_Debug) if(g_Config.m_Debug)
{ {

View file

@ -445,10 +445,7 @@ IGraphics::CTextureHandle CMapImages::UploadEntityLayerText(int TextureSize, int
UpdateEntityLayerText(pMem, PixelSize, Width, Height, TextureSize, MaxWidth, YOffset, 2, 255); UpdateEntityLayerText(pMem, PixelSize, Width, Height, TextureSize, MaxWidth, YOffset, 2, 255);
const int TextureLoadFlag = (Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE) | IGraphics::TEXLOAD_NO_2D_TEXTURE; const int TextureLoadFlag = (Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE) | IGraphics::TEXLOAD_NO_2D_TEXTURE;
IGraphics::CTextureHandle Texture = Graphics()->LoadTextureRaw(Width, Height, CImageInfo::FORMAT_RGBA, pMem, TextureLoadFlag); return Graphics()->LoadTextureRawMove(Width, Height, CImageInfo::FORMAT_RGBA, pMem, TextureLoadFlag);
free(pMem);
return Texture;
} }
void CMapImages::UpdateEntityLayerText(void *pTexBuffer, size_t PixelSize, size_t TexWidth, size_t TexHeight, int TextureSize, int MaxWidth, int YOffset, int NumbersPower, int MaxNumber) void CMapImages::UpdateEntityLayerText(void *pTexBuffer, size_t PixelSize, size_t TexWidth, size_t TexHeight, int TextureSize, int MaxWidth, int YOffset, int NumbersPower, int MaxNumber)

View file

@ -2197,8 +2197,7 @@ int CMenus::MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser
pData[i * Step + 1] = v; pData[i * Step + 1] = v;
pData[i * Step + 2] = v; pData[i * Step + 2] = v;
} }
MenuImage.m_GreyTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, 0); MenuImage.m_GreyTexture = pSelf->Graphics()->LoadTextureRawMove(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, 0);
pSelf->Graphics()->FreePNG(&Info);
str_truncate(MenuImage.m_aName, sizeof(MenuImage.m_aName), pName, str_length(pName) - str_length(pExtension)); str_truncate(MenuImage.m_aName, sizeof(MenuImage.m_aName), pName, str_length(pName) - str_length(pExtension));
pSelf->m_vMenuImages.push_back(MenuImage); pSelf->m_vMenuImages.push_back(MenuImage);

View file

@ -1908,8 +1908,8 @@ void CMenus::LoadCommunityIconFinish(const char *pCommunityId, CImageInfo &&Info
pData[i * Step + 1] = v; pData[i * Step + 1] = v;
pData[i * Step + 2] = v; pData[i * Step + 2] = v;
} }
CommunityIcon.m_GreyTexture = Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, 0); CommunityIcon.m_GreyTexture = Graphics()->LoadTextureRawMove(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, 0);
Graphics()->FreePNG(&Info); Info.m_pData = nullptr;
auto ExistingIcon = std::find_if(m_vCommunityIcons.begin(), m_vCommunityIcons.end(), [pCommunityId](const SCommunityIcon &Element) { auto ExistingIcon = std::find_if(m_vCommunityIcons.begin(), m_vCommunityIcons.end(), [pCommunityId](const SCommunityIcon &Element) {
return str_comp(Element.m_aCommunityId, pCommunityId) == 0; return str_comp(Element.m_aCommunityId, pCommunityId) == 0;

View file

@ -5166,8 +5166,8 @@ void CEditor::RenderFileDialog()
if(Graphics()->LoadPNG(&m_FilePreviewImageInfo, aBuffer, m_vpFilteredFileList[m_FilesSelectedIndex]->m_StorageType)) if(Graphics()->LoadPNG(&m_FilePreviewImageInfo, aBuffer, m_vpFilteredFileList[m_FilesSelectedIndex]->m_StorageType))
{ {
Graphics()->UnloadTexture(&m_FilePreviewImage); Graphics()->UnloadTexture(&m_FilePreviewImage);
m_FilePreviewImage = Graphics()->LoadTextureRaw(m_FilePreviewImageInfo.m_Width, m_FilePreviewImageInfo.m_Height, m_FilePreviewImageInfo.m_Format, m_FilePreviewImageInfo.m_pData, 0); m_FilePreviewImage = Graphics()->LoadTextureRawMove(m_FilePreviewImageInfo.m_Width, m_FilePreviewImageInfo.m_Height, m_FilePreviewImageInfo.m_Format, m_FilePreviewImageInfo.m_pData, 0);
Graphics()->FreePNG(&m_FilePreviewImageInfo); m_FilePreviewImageInfo.m_pData = nullptr;
m_FilePreviewState = PREVIEW_LOADED; m_FilePreviewState = PREVIEW_LOADED;
} }
else else