mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-13 02:21:53 +00:00
Merge pull request #10801 from unknownbrackets/sdl-shutdown
Fix shutdown segfault in SDL, fix headless
This commit is contained in:
commit
0130e75852
@ -218,7 +218,8 @@ int getDisplayNumber(void) {
|
||||
|
||||
void SystemToast(const char *text) {
|
||||
#ifdef _WIN32
|
||||
MessageBox(0, text, "Toast!", MB_ICONINFORMATION);
|
||||
std::wstring str = ConvertUTF8ToWString(text);
|
||||
MessageBox(0, str.c_str(), L"Toast!", MB_ICONINFORMATION);
|
||||
#else
|
||||
puts(text);
|
||||
#endif
|
||||
@ -256,7 +257,8 @@ void LaunchBrowser(const char *url) {
|
||||
#if defined(MOBILE_DEVICE)
|
||||
ILOG("Would have gone to %s but LaunchBrowser is not implemented on this platform", url);
|
||||
#elif defined(_WIN32)
|
||||
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
||||
std::wstring wurl = ConvertUTF8ToWString(url);
|
||||
ShellExecute(NULL, L"open", wurl.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
#elif defined(__APPLE__)
|
||||
std::string command = std::string("open ") + url;
|
||||
system(command.c_str());
|
||||
@ -273,7 +275,8 @@ void LaunchMarket(const char *url) {
|
||||
#if defined(MOBILE_DEVICE)
|
||||
ILOG("Would have gone to %s but LaunchMarket is not implemented on this platform", url);
|
||||
#elif defined(_WIN32)
|
||||
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
||||
std::wstring wurl = ConvertUTF8ToWString(url);
|
||||
ShellExecute(NULL, L"open", wurl.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
#elif defined(__APPLE__)
|
||||
std::string command = std::string("open ") + url;
|
||||
system(command.c_str());
|
||||
@ -290,7 +293,8 @@ void LaunchEmail(const char *email_address) {
|
||||
#if defined(MOBILE_DEVICE)
|
||||
ILOG("Would have opened your email client for %s but LaunchEmail is not implemented on this platform", email_address);
|
||||
#elif defined(_WIN32)
|
||||
ShellExecute(NULL, "open", (std::string("mailto:") + email_address).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
std::wstring mailto = std::wstring(L"mailto:") + ConvertUTF8ToWString(email_address);
|
||||
ShellExecute(NULL, L"open", mailto.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
#elif defined(__APPLE__)
|
||||
std::string command = std::string("open mailto:") + email_address;
|
||||
system(command.c_str());
|
||||
@ -921,11 +925,12 @@ int main(int argc, char *argv[]) {
|
||||
if (!useEmuThread) {
|
||||
NativeShutdownGraphics();
|
||||
}
|
||||
graphicsContext->Shutdown();
|
||||
graphicsContext->ThreadEnd();
|
||||
graphicsContext->ShutdownFromRenderThread();
|
||||
|
||||
NativeShutdown();
|
||||
|
||||
// Destroys Draw, which is used in NativeShutdown to shutdown.
|
||||
graphicsContext->ShutdownFromRenderThread();
|
||||
delete graphicsContext;
|
||||
|
||||
SDL_PauseAudio(1);
|
||||
|
@ -32,11 +32,13 @@
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/timeutil.h"
|
||||
#include "gfx/gl_common.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
#include "file/vfs.h"
|
||||
#include "file/zip_read.h"
|
||||
#include "thin3d/thin3d_create.h"
|
||||
#include "thin3d/GLRenderManager.h"
|
||||
|
||||
const bool WINDOW_VISIBLE = false;
|
||||
const int WINDOW_WIDTH = 480;
|
||||
@ -53,20 +55,47 @@ SDL_Window *CreateHiddenWindow() {
|
||||
class GLDummyGraphicsContext : public DummyGraphicsContext {
|
||||
public:
|
||||
GLDummyGraphicsContext() {
|
||||
CheckGLExtensions();
|
||||
draw_ = Draw::T3DCreateGLContext();
|
||||
SetGPUBackend(GPUBackend::OPENGL);
|
||||
bool success = draw_->CreatePresets();
|
||||
assert(success);
|
||||
}
|
||||
~GLDummyGraphicsContext() { delete draw_; }
|
||||
|
||||
bool InitFromRenderThread(std::string *errorMessage) override;
|
||||
|
||||
void ShutdownFromRenderThread() override {
|
||||
delete draw_;
|
||||
draw_ = nullptr;
|
||||
|
||||
SDL_GL_DeleteContext(glContext_);
|
||||
glContext_ = nullptr;
|
||||
SDL_DestroyWindow(screen_);
|
||||
screen_ = nullptr;
|
||||
}
|
||||
|
||||
Draw::DrawContext *GetDrawContext() override {
|
||||
return draw_;
|
||||
}
|
||||
|
||||
void ThreadStart() override {
|
||||
renderManager_->ThreadStart();
|
||||
}
|
||||
|
||||
bool ThreadFrame() override {
|
||||
return renderManager_->ThreadFrame();
|
||||
}
|
||||
|
||||
void ThreadEnd() override {
|
||||
renderManager_->ThreadEnd();
|
||||
}
|
||||
|
||||
void StopThread() override {
|
||||
renderManager_->WaitUntilQueueIdle();
|
||||
renderManager_->StopThread();
|
||||
}
|
||||
|
||||
private:
|
||||
Draw::DrawContext *draw_;
|
||||
GLRenderManager *renderManager_ = nullptr;
|
||||
SDL_Window *screen_;
|
||||
SDL_GLContext glContext_;
|
||||
};
|
||||
|
||||
void SDLHeadlessHost::LoadNativeAssets() {
|
||||
@ -75,7 +104,7 @@ void SDLHeadlessHost::LoadNativeAssets() {
|
||||
VFSRegister("", new DirectoryAssetReader("../"));
|
||||
}
|
||||
|
||||
bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) {
|
||||
bool GLDummyGraphicsContext::InitFromRenderThread(std::string *errorMessage) {
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
// TODO
|
||||
@ -115,29 +144,72 @@ bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext *
|
||||
}
|
||||
#endif
|
||||
|
||||
CheckGLExtensions();
|
||||
draw_ = Draw::T3DCreateGLContext();
|
||||
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
SetGPUBackend(GPUBackend::OPENGL);
|
||||
bool success = draw_->CreatePresets();
|
||||
assert(success);
|
||||
renderManager_->SetSwapFunction([&]() {
|
||||
SDL_GL_SwapWindow(screen_);
|
||||
});
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) {
|
||||
GraphicsContext *graphicsContext = new GLDummyGraphicsContext();
|
||||
*ctx = graphicsContext;
|
||||
gfx_ = graphicsContext;
|
||||
|
||||
std::thread th([&]{
|
||||
while (threadState_ == RenderThreadState::IDLE)
|
||||
sleep_ms(1);
|
||||
threadState_ = RenderThreadState::STARTING;
|
||||
|
||||
std::string err;
|
||||
if (!gfx_->InitFromRenderThread(&err)) {
|
||||
threadState_ = RenderThreadState::START_FAILED;
|
||||
return;
|
||||
}
|
||||
gfx_->ThreadStart();
|
||||
threadState_ = RenderThreadState::STARTED;
|
||||
|
||||
while (threadState_ != RenderThreadState::STOP_REQUESTED) {
|
||||
if (!gfx_->ThreadFrame()) {
|
||||
break;
|
||||
}
|
||||
gfx_->SwapBuffers();
|
||||
}
|
||||
|
||||
threadState_ = RenderThreadState::STOPPING;
|
||||
gfx_->ThreadEnd();
|
||||
gfx_->ShutdownFromRenderThread();
|
||||
threadState_ = RenderThreadState::STOPPED;
|
||||
});
|
||||
th.detach();
|
||||
|
||||
LoadNativeAssets();
|
||||
|
||||
return true;
|
||||
threadState_ = RenderThreadState::START_REQUESTED;
|
||||
while (threadState_ == RenderThreadState::START_REQUESTED || threadState_ == RenderThreadState::STARTING)
|
||||
sleep_ms(1);
|
||||
|
||||
return threadState_ == RenderThreadState::STARTED;
|
||||
}
|
||||
|
||||
void SDLHeadlessHost::ShutdownGraphics() {
|
||||
gfx_->StopThread();
|
||||
while (threadState_ != RenderThreadState::STOPPED)
|
||||
sleep_ms(1);
|
||||
|
||||
gfx_->Shutdown();
|
||||
delete gfx_;
|
||||
gfx_ = nullptr;
|
||||
|
||||
SDL_GL_DeleteContext(glContext_);
|
||||
glContext_ = nullptr;
|
||||
SDL_DestroyWindow(screen_);
|
||||
screen_ = nullptr;
|
||||
}
|
||||
|
||||
void SDLHeadlessHost::SwapBuffers() {
|
||||
gfx_->SwapBuffers();
|
||||
SDL_GL_SwapWindow(screen_);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -38,9 +38,19 @@ public:
|
||||
protected:
|
||||
void LoadNativeAssets();
|
||||
|
||||
SDL_Window *screen_;
|
||||
SDL_GLContext glContext_;
|
||||
enum class RenderThreadState {
|
||||
IDLE,
|
||||
START_REQUESTED,
|
||||
STARTING,
|
||||
START_FAILED,
|
||||
STARTED,
|
||||
STOP_REQUESTED,
|
||||
STOPPING,
|
||||
STOPPED,
|
||||
};
|
||||
|
||||
GraphicsContext *gfx_;
|
||||
volatile RenderThreadState threadState_ = RenderThreadState::IDLE;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user