mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-16 04:13:50 +00:00
[steam] Avoid crash taking screenshots after Steam client is closed
This commit is contained in:
parent
2f472f0760
commit
c8999af6d6
@ -48,6 +48,10 @@
|
||||
#include "ui/intern.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#ifdef ENABLE_STEAM
|
||||
#include "steam/steam.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
@ -366,6 +370,11 @@ void defer_invalid_rect(const gfx::Rect& rc)
|
||||
// Manager event handler.
|
||||
bool CustomizedGuiManager::onProcessMessage(Message* msg)
|
||||
{
|
||||
#ifdef ENABLE_STEAM
|
||||
if (auto steamAPI = steam::SteamAPI::instance())
|
||||
steamAPI->runCallbacks();
|
||||
#endif
|
||||
|
||||
switch (msg->type()) {
|
||||
|
||||
case kCloseDisplayMessage: {
|
||||
|
@ -19,12 +19,34 @@
|
||||
|
||||
namespace steam {
|
||||
|
||||
typedef uint32_t HSteamPipe;
|
||||
typedef uint32_t HSteamUser;
|
||||
typedef uint32_t ScreenshotHandle;
|
||||
typedef void* ISteamScreenshots;
|
||||
|
||||
enum {
|
||||
// Last callback received from Steam client when it's Steam is closed
|
||||
kSteamServersDisconnected = 103,
|
||||
kSteamUndocumentedLastCallback = 1009,
|
||||
};
|
||||
|
||||
struct CallbackMsg_t {
|
||||
HSteamUser steamUser;
|
||||
int callback;
|
||||
uint8_t* pubParam;
|
||||
int cubParam;
|
||||
};
|
||||
|
||||
// Steam main API
|
||||
typedef bool __cdecl (*SteamAPI_Init_Func)();
|
||||
typedef void __cdecl (*SteamAPI_Shutdown_Func)();
|
||||
typedef HSteamPipe __cdecl (*SteamAPI_GetHSteamPipe_Func)();
|
||||
|
||||
// Steam callbacks
|
||||
typedef void __cdecl (*SteamAPI_ManualDispatch_Init_Func)();
|
||||
typedef void __cdecl (*SteamAPI_ManualDispatch_RunFrame_Func)(HSteamPipe);
|
||||
typedef bool __cdecl (*SteamAPI_ManualDispatch_GetNextCallback_Func)(HSteamPipe, CallbackMsg_t*);
|
||||
typedef void __cdecl (*SteamAPI_ManualDispatch_FreeLastCallback_Func)(HSteamPipe);
|
||||
|
||||
// ISteamScreenshots
|
||||
typedef ISteamScreenshots* __cdecl (*SteamAPI_SteamScreenshots_v003_Func)();
|
||||
@ -67,6 +89,21 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
// Get functions to dispatch callbacks manually
|
||||
auto SteamAPI_ManualDispatch_Init = GETPROC(SteamAPI_ManualDispatch_Init);
|
||||
SteamAPI_ManualDispatch_RunFrame = GETPROC(SteamAPI_ManualDispatch_RunFrame);
|
||||
SteamAPI_ManualDispatch_GetNextCallback = GETPROC(SteamAPI_ManualDispatch_GetNextCallback);
|
||||
SteamAPI_ManualDispatch_FreeLastCallback = GETPROC(SteamAPI_ManualDispatch_FreeLastCallback);
|
||||
auto SteamAPI_GetHSteamPipe = GETPROC(SteamAPI_GetHSteamPipe);
|
||||
if (SteamAPI_ManualDispatch_Init &&
|
||||
SteamAPI_ManualDispatch_RunFrame &&
|
||||
SteamAPI_ManualDispatch_GetNextCallback &&
|
||||
SteamAPI_ManualDispatch_FreeLastCallback &&
|
||||
SteamAPI_GetHSteamPipe) {
|
||||
SteamAPI_ManualDispatch_Init();
|
||||
m_pipe = SteamAPI_GetHSteamPipe();
|
||||
}
|
||||
|
||||
LOG("STEAM: Steam initialized\n");
|
||||
m_initialized = true;
|
||||
}
|
||||
@ -81,13 +118,44 @@ public:
|
||||
SteamAPI_Shutdown();
|
||||
}
|
||||
|
||||
base::unload_dll(m_steamLib);
|
||||
unloadLib();
|
||||
}
|
||||
|
||||
bool initialized() const {
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
void runCallbacks() {
|
||||
if (!m_pipe)
|
||||
return;
|
||||
|
||||
ASSERT(SteamAPI_ManualDispatch_RunFrame);
|
||||
ASSERT(SteamAPI_ManualDispatch_GetNextCallback);
|
||||
ASSERT(SteamAPI_ManualDispatch_FreeLastCallback);
|
||||
|
||||
SteamAPI_ManualDispatch_RunFrame(m_pipe);
|
||||
|
||||
CallbackMsg_t msg;
|
||||
if (SteamAPI_ManualDispatch_GetNextCallback(m_pipe, &msg)) {
|
||||
//TRACEARGS("SteamAPI_ManualDispatch_GetNextCallback", msg.callback);
|
||||
|
||||
bool disconnected = false;
|
||||
if (msg.callback == kSteamServersDisconnected ||
|
||||
msg.callback == kSteamUndocumentedLastCallback) {
|
||||
disconnected = true;
|
||||
}
|
||||
SteamAPI_ManualDispatch_FreeLastCallback(m_pipe);
|
||||
|
||||
// If the Steam client is closed, we have to unload the DLL and
|
||||
// don't use the pipe or any Steam API at all, in other case we
|
||||
// would crash.
|
||||
if (disconnected) {
|
||||
LOG("STEAM: Disconnected\n");
|
||||
unloadLib();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool writeScreenshot(void* rgbBuffer,
|
||||
uint32_t sizeInBytes,
|
||||
int width, int height) {
|
||||
@ -112,8 +180,21 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void unloadLib() {
|
||||
base::unload_dll(m_steamLib);
|
||||
m_steamLib = nullptr;
|
||||
m_initialized = false;
|
||||
m_pipe = 0;
|
||||
}
|
||||
|
||||
bool m_initialized = false;
|
||||
base::dll m_steamLib = nullptr;
|
||||
|
||||
// To handle callbacks manually
|
||||
HSteamPipe m_pipe = 0;
|
||||
SteamAPI_ManualDispatch_RunFrame_Func SteamAPI_ManualDispatch_RunFrame = nullptr;
|
||||
SteamAPI_ManualDispatch_GetNextCallback_Func SteamAPI_ManualDispatch_GetNextCallback = nullptr;
|
||||
SteamAPI_ManualDispatch_FreeLastCallback_Func SteamAPI_ManualDispatch_FreeLastCallback = nullptr;
|
||||
};
|
||||
|
||||
SteamAPI* g_instance = nullptr;
|
||||
@ -144,6 +225,11 @@ bool SteamAPI::initialized() const
|
||||
return m_impl->initialized();
|
||||
}
|
||||
|
||||
void SteamAPI::runCallbacks()
|
||||
{
|
||||
m_impl->runCallbacks();
|
||||
}
|
||||
|
||||
bool SteamAPI::writeScreenshot(void* rgbBuffer,
|
||||
uint32_t sizeInBytes,
|
||||
int width, int height)
|
||||
|
@ -19,6 +19,7 @@ public:
|
||||
~SteamAPI();
|
||||
|
||||
bool initialized() const;
|
||||
void runCallbacks();
|
||||
|
||||
bool writeScreenshot(void* rgbBuffer,
|
||||
uint32_t sizeInBytes,
|
||||
|
Loading…
Reference in New Issue
Block a user