Merge pull request #10801 from unknownbrackets/sdl-shutdown

Fix shutdown segfault in SDL, fix headless
This commit is contained in:
Henrik Rydgård 2018-03-26 21:10:48 +02:00 committed by GitHub
commit 0130e75852
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 21 deletions

View File

@ -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);

View File

@ -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

View File

@ -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