mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Merge #6414
6414: Save screenshot in separate thread to avoid lags r=edg-l a=Robyt3 Encoding the image as PNG and saving it to a file comprises the majority of the time when taking a screenshot. To avoid the client freezing while a screenshot is being saved, this task is moved to a separate background thread. ## Checklist - [X] Tested the change ingame - [ ] Provided screenshots if it is a visual change - [ ] Tested in combination with possibly related configuration options - [ ] Written a unit test (especially base/) or added coverage to integration test - [ ] Considered possible null pointers and out of bounds array indexing - [ ] Changed no physics that affect existing maps - [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional) Co-authored-by: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
commit
e05f88fb7b
|
@ -11,11 +11,14 @@
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
|
|
||||||
#include <engine/console.h>
|
#include <engine/console.h>
|
||||||
|
#include <engine/engine.h>
|
||||||
#include <engine/gfx/image_loader.h>
|
#include <engine/gfx/image_loader.h>
|
||||||
#include <engine/gfx/image_manipulation.h>
|
#include <engine/gfx/image_manipulation.h>
|
||||||
#include <engine/graphics.h>
|
#include <engine/graphics.h>
|
||||||
#include <engine/shared/config.h>
|
#include <engine/shared/config.h>
|
||||||
|
#include <engine/shared/jobs.h>
|
||||||
#include <engine/storage.h>
|
#include <engine/storage.h>
|
||||||
|
|
||||||
#include <game/generated/client_data.h>
|
#include <game/generated/client_data.h>
|
||||||
#include <game/generated/client_data7.h>
|
#include <game/generated/client_data7.h>
|
||||||
#include <game/localization.h>
|
#include <game/localization.h>
|
||||||
|
@ -811,6 +814,55 @@ void CGraphics_Threaded::KickCommandBuffer()
|
||||||
m_pCommandBuffer->Reset();
|
m_pCommandBuffer->Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CScreenshotSaveJob : public IJob
|
||||||
|
{
|
||||||
|
IStorage *m_pStorage;
|
||||||
|
IConsole *m_pConsole;
|
||||||
|
char m_aName[IO_MAX_PATH_LENGTH];
|
||||||
|
int m_Width;
|
||||||
|
int m_Height;
|
||||||
|
void *m_pData;
|
||||||
|
|
||||||
|
void Run() override
|
||||||
|
{
|
||||||
|
char aWholePath[IO_MAX_PATH_LENGTH];
|
||||||
|
char aBuf[64 + IO_MAX_PATH_LENGTH];
|
||||||
|
IOHANDLE File = m_pStorage->OpenFile(m_aName, IOFLAG_WRITE, IStorage::TYPE_SAVE, aWholePath, sizeof(aWholePath));
|
||||||
|
if(File)
|
||||||
|
{
|
||||||
|
TImageByteBuffer ByteBuffer;
|
||||||
|
SImageByteBuffer ImageByteBuffer(&ByteBuffer);
|
||||||
|
|
||||||
|
if(SavePNG(IMAGE_FORMAT_RGBA, (const uint8_t *)m_pData, ImageByteBuffer, m_Width, m_Height))
|
||||||
|
io_write(File, &ByteBuffer.front(), ByteBuffer.size());
|
||||||
|
io_close(File);
|
||||||
|
|
||||||
|
str_format(aBuf, sizeof(aBuf), "saved screenshot to '%s'", aWholePath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str_format(aBuf, sizeof(aBuf), "failed to save screenshot to '%s'", aWholePath);
|
||||||
|
}
|
||||||
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf, ColorRGBA(1.0f, 0.6f, 0.3f, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
CScreenshotSaveJob(IStorage *pStorage, IConsole *pConsole, const char *pName, int Width, int Height, void *pData) :
|
||||||
|
m_pStorage(pStorage),
|
||||||
|
m_pConsole(pConsole),
|
||||||
|
m_Width(Width),
|
||||||
|
m_Height(Height),
|
||||||
|
m_pData(pData)
|
||||||
|
{
|
||||||
|
str_copy(m_aName, pName);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~CScreenshotSaveJob()
|
||||||
|
{
|
||||||
|
free(m_pData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
bool CGraphics_Threaded::ScreenshotDirect()
|
bool CGraphics_Threaded::ScreenshotDirect()
|
||||||
{
|
{
|
||||||
// add swap command
|
// add swap command
|
||||||
|
@ -831,28 +883,7 @@ bool CGraphics_Threaded::ScreenshotDirect()
|
||||||
|
|
||||||
if(Image.m_pData)
|
if(Image.m_pData)
|
||||||
{
|
{
|
||||||
char aWholePath[IO_MAX_PATH_LENGTH];
|
m_pEngine->AddJob(std::make_shared<CScreenshotSaveJob>(m_pStorage, m_pConsole, m_aScreenshotName, Image.m_Width, Image.m_Height, Image.m_pData));
|
||||||
char aBuf[64 + IO_MAX_PATH_LENGTH];
|
|
||||||
|
|
||||||
IOHANDLE File = m_pStorage->OpenFile(m_aScreenshotName, IOFLAG_WRITE, IStorage::TYPE_SAVE, aWholePath, sizeof(aWholePath));
|
|
||||||
if(File)
|
|
||||||
{
|
|
||||||
TImageByteBuffer ByteBuffer;
|
|
||||||
SImageByteBuffer ImageByteBuffer(&ByteBuffer);
|
|
||||||
|
|
||||||
if(SavePNG(IMAGE_FORMAT_RGBA, (const uint8_t *)Image.m_pData, ImageByteBuffer, Image.m_Width, Image.m_Height))
|
|
||||||
io_write(File, &ByteBuffer.front(), ByteBuffer.size());
|
|
||||||
io_close(File);
|
|
||||||
|
|
||||||
str_format(aBuf, sizeof(aBuf), "saved screenshot to '%s'", aWholePath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
str_format(aBuf, sizeof(aBuf), "failed to save screenshot to '%s'", aWholePath);
|
|
||||||
}
|
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf, ColorRGBA(1.0f, 0.6f, 0.3f, 1.0f));
|
|
||||||
|
|
||||||
free(Image.m_pData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DidSwap;
|
return DidSwap;
|
||||||
|
@ -2836,6 +2867,7 @@ int CGraphics_Threaded::Init()
|
||||||
// fetch pointers
|
// fetch pointers
|
||||||
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
||||||
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||||
|
m_pEngine = Kernel()->RequestInterface<IEngine>();
|
||||||
|
|
||||||
// init textures
|
// init textures
|
||||||
m_FirstFreeTexture = 0;
|
m_FirstFreeTexture = 0;
|
||||||
|
|
|
@ -802,6 +802,7 @@ class CGraphics_Threaded : public IEngineGraphics
|
||||||
//
|
//
|
||||||
class IStorage *m_pStorage;
|
class IStorage *m_pStorage;
|
||||||
class IConsole *m_pConsole;
|
class IConsole *m_pConsole;
|
||||||
|
class IEngine *m_pEngine;
|
||||||
|
|
||||||
int m_CurIndex;
|
int m_CurIndex;
|
||||||
|
|
||||||
|
@ -817,7 +818,7 @@ class CGraphics_Threaded : public IEngineGraphics
|
||||||
float m_Rotation;
|
float m_Rotation;
|
||||||
int m_Drawing;
|
int m_Drawing;
|
||||||
bool m_DoScreenshot;
|
bool m_DoScreenshot;
|
||||||
char m_aScreenshotName[128];
|
char m_aScreenshotName[IO_MAX_PATH_LENGTH];
|
||||||
|
|
||||||
CTextureHandle m_InvalidTexture;
|
CTextureHandle m_InvalidTexture;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue