From 3ab7510c7f4695afa1a21426f791de288329878d Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 30 May 2017 12:02:00 +0100 Subject: [PATCH] Avoid calling XOpenDisplay multiple times, fixes crashes on Intel Mesa * See https://bugs.freedesktop.org/show_bug.cgi?id=99831 https://bugs.freedesktop.org/show_bug.cgi?id=54971 * It's not clear if it's invalid to call XOpenDisplay more than once but at the very least it's only really used as convenience to avoid plumbing the display handle through. --- qrenderdoc/Code/qrenderdoc.cpp | 9 +++++ renderdoc/api/replay/renderdoc_replay.h | 16 ++++++++ renderdoc/core/core.cpp | 21 +++++++++++ renderdoc/core/core.h | 5 +++ renderdoc/driver/gl/gl_hooks_egl.cpp | 10 +---- renderdoc/driver/gl/gl_hooks_linux.cpp | 6 +-- renderdoc/driver/gl/gl_replay_egl.cpp | 22 ----------- renderdoc/driver/gl/gl_replay_linux.cpp | 8 +--- renderdoc/replay/entry_points.cpp | 11 ++++++ renderdoccmd/renderdoccmd.cpp | 66 +++++++++++++++++++++++++-------- renderdoccmd/renderdoccmd.h | 12 +++--- renderdoccmd/renderdoccmd_android.cpp | 3 +- renderdoccmd/renderdoccmd_apple.cpp | 3 +- renderdoccmd/renderdoccmd_linux.cpp | 27 ++++++++------ renderdoccmd/renderdoccmd_win32.cpp | 14 ++++--- 15 files changed, 150 insertions(+), 83 deletions(-) diff --git a/qrenderdoc/Code/qrenderdoc.cpp b/qrenderdoc/Code/qrenderdoc.cpp index e1bfebf8..8c168c45 100644 --- a/qrenderdoc/Code/qrenderdoc.cpp +++ b/qrenderdoc/Code/qrenderdoc.cpp @@ -182,6 +182,15 @@ int main(int argc, char *argv[]) GUIInvoke::init(); PythonContext::GlobalInit(); + + { + GlobalEnvironment env; +#if defined(RENDERDOC_PLATFORM_LINUX) + env.xlibDisplay = QX11Info::display(); +#endif + RENDERDOC_InitGlobalEnv(env, rdctype::array()); + } + { CaptureContext ctx(filename, remoteHost, remoteIdent, temp, config); diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index c60a545c..36260fca 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -25,6 +25,7 @@ #pragma once +#include #include template @@ -115,6 +116,10 @@ struct XlibWindowData Drawable window; }; +#else + +typedef void *Display; + #endif #if defined(RENDERDOC_WINDOWING_XCB) @@ -167,6 +172,13 @@ enum class WindowingSystem : uint32_t Android, }; +DOCUMENT(R"(Internal structure used for initialising environment in a replay application.)"); +struct GlobalEnvironment +{ + DOCUMENT("The handle to the X display to use internally. If left ``NULL``, one will be opened."); + Display *xlibDisplay = NULL; +}; + // needs to be declared up here for reference in basic_types extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_FreeArrayMem(const void *mem); @@ -1367,6 +1379,10 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_UpdateVulkanLayerRegistrati // Miscellaneous! ////////////////////////////////////////////////////////////////////////// +DOCUMENT("Internal function for initialising global process environment in a replay program."); +extern "C" RENDERDOC_API void RENDERDOC_CC +RENDERDOC_InitGlobalEnv(GlobalEnvironment env, const rdctype::array &args); + DOCUMENT("Internal function for triggering exception handler."); extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_TriggerExceptionHandler(void *exceptionPtrs, bool32 crashed); diff --git a/renderdoc/core/core.cpp b/renderdoc/core/core.cpp index 83b855ab..da9dda75 100644 --- a/renderdoc/core/core.cpp +++ b/renderdoc/core/core.cpp @@ -36,6 +36,10 @@ #include "stb/stb_image.h" #include "crash_handler.h" +#if ENABLED(RDOC_LINUX) && ENABLED(RDOC_XLIB) +#include +#endif + // from image_viewer.cpp ReplayStatus IMG_CreateReplayDevice(const char *logfile, IReplayDriver **driver); @@ -404,6 +408,23 @@ void RenderDoc::Shutdown() } } +void RenderDoc::ProcessGlobalEnvironment(GlobalEnvironment env, const std::vector &args) +{ + m_GlobalEnv = env; + +#if ENABLED(RDOC_LINUX) && ENABLED(RDOC_XLIB) + if(!m_GlobalEnv.xlibDisplay) + m_GlobalEnv.xlibDisplay = XOpenDisplay(NULL); +#endif + + if(!args.empty()) + { + RDCDEBUG("Replay application launched with parameters:"); + for(size_t i = 0; i < args.size(); i++) + RDCDEBUG("[%u]: %s", (uint32_t)i, args[i].c_str()); + } +} + bool RenderDoc::MatchClosestWindow(void *&dev, void *&wnd) { DeviceWnd dw(dev, wnd); diff --git a/renderdoc/core/core.h b/renderdoc/core/core.h index cbb33521..1752f875 100644 --- a/renderdoc/core/core.h +++ b/renderdoc/core/core.h @@ -205,6 +205,9 @@ public: void Initialise(); void Shutdown(); + const GlobalEnvironment GetGlobalEnvironment() { return m_GlobalEnv; } + void ProcessGlobalEnvironment(GlobalEnvironment env, const std::vector &args); + void RegisterShutdownFunction(ShutdownFunction func) { m_ShutdownFunctions.insert(func); } void SetReplayApp(bool replay) { m_Replay = replay; } bool IsReplayApp() const { return m_Replay; } @@ -350,6 +353,8 @@ private: vector m_FocusKeys; vector m_CaptureKeys; + GlobalEnvironment m_GlobalEnv; + FrameTimer m_FrameTimer; string m_LoggingFilename; diff --git a/renderdoc/driver/gl/gl_hooks_egl.cpp b/renderdoc/driver/gl/gl_hooks_egl.cpp index 4dd147a0..bc5cf90d 100644 --- a/renderdoc/driver/gl/gl_hooks_egl.cpp +++ b/renderdoc/driver/gl/gl_hooks_egl.cpp @@ -215,15 +215,9 @@ public: break; } #endif - case WindowingSystem::Unknown: { -#if ENABLED(RDOC_LINUX) - // allow undefined so that internally we can create a window-less context - Display *dpy = XOpenDisplay(NULL); - if(dpy == NULL) - return ret; -#endif + case WindowingSystem::Unknown: + // allow WindowingSystem::Unknown so that internally we can create a window-less context break; - } default: RDCERR("Unexpected window system %u", system); break; } diff --git a/renderdoc/driver/gl/gl_hooks_linux.cpp b/renderdoc/driver/gl/gl_hooks_linux.cpp index 4a50f742..445d6916 100644 --- a/renderdoc/driver/gl/gl_hooks_linux.cpp +++ b/renderdoc/driver/gl/gl_hooks_linux.cpp @@ -241,8 +241,8 @@ public: } else if(system == WindowingSystem::Unknown) { - // allow undefined so that internally we can create a window-less context - dpy = XOpenDisplay(NULL); + // allow WindowingSystem::Unknown so that internally we can create a window-less context + dpy = RenderDoc::Inst().GetGlobalEnvironment().xlibDisplay; if(dpy == NULL) return ret; @@ -276,7 +276,6 @@ public: if(fbcfg == NULL) { - XCloseDisplay(dpy); RDCERR("Couldn't choose default framebuffer config"); return ret; } @@ -317,7 +316,6 @@ public: if(ctx == NULL) { - XCloseDisplay(dpy); RDCERR("Couldn't create %d.%d context - something changed since creation", GLCoreVersion / 10, GLCoreVersion % 10); return ret; diff --git a/renderdoc/driver/gl/gl_replay_egl.cpp b/renderdoc/driver/gl/gl_replay_egl.cpp index eaad0fef..beabeef9 100644 --- a/renderdoc/driver/gl/gl_replay_egl.cpp +++ b/renderdoc/driver/gl/gl_replay_egl.cpp @@ -117,16 +117,6 @@ ReplayStatus GLES_CreateReplayDevice(const char *logfile, IReplayDriver **driver initParams.isSRGB = 0; #endif -#if DISABLED(RDOC_ANDROID) - Display *dpy = XOpenDisplay(NULL); - - if(dpy == NULL) - { - RDCERR("Couldn't open default X display"); - return ReplayStatus::APIInitFailed; - } -#endif - eglBindAPIProc(EGL_OPENGL_ES_API); EGLDisplay eglDisplay = eglGetDisplayProc(EGL_DEFAULT_DISPLAY); @@ -167,9 +157,6 @@ ReplayStatus GLES_CreateReplayDevice(const char *logfile, IReplayDriver **driver EGLContext ctx = eglCreateContextProc(eglDisplay, config, EGL_NO_CONTEXT, ctxAttribs); if(ctx == NULL) { -#if DISABLED(RDOC_ANDROID) - XCloseDisplay(dpy); -#endif GLReplay::PostContextShutdownCounters(); RDCERR("Couldn't create GL ES 3.x context - RenderDoc requires OpenGL ES 3.x availability"); return ReplayStatus::APIHardwareUnsupported; @@ -182,9 +169,6 @@ ReplayStatus GLES_CreateReplayDevice(const char *logfile, IReplayDriver **driver { RDCERR("Couldn't create a suitable PBuffer"); eglDestroySurfaceProc(eglDisplay, pbuffer); -#if DISABLED(RDOC_ANDROID) - XCloseDisplay(dpy); -#endif GLReplay::PostContextShutdownCounters(); return ReplayStatus::APIInitFailed; } @@ -195,9 +179,6 @@ ReplayStatus GLES_CreateReplayDevice(const char *logfile, IReplayDriver **driver RDCERR("Couldn't active the created GL ES context"); eglDestroySurfaceProc(eglDisplay, pbuffer); eglDestroyContextProc(eglDisplay, ctx); -#if DISABLED(RDOC_ANDROID) - XCloseDisplay(dpy); -#endif GLReplay::PostContextShutdownCounters(); return ReplayStatus::APIInitFailed; } @@ -210,9 +191,6 @@ ReplayStatus GLES_CreateReplayDevice(const char *logfile, IReplayDriver **driver { eglDestroySurfaceProc(eglDisplay, pbuffer); eglDestroyContextProc(eglDisplay, ctx); -#if DISABLED(RDOC_ANDROID) - XCloseDisplay(dpy); -#endif GLReplay::PostContextShutdownCounters(); return ReplayStatus::APIHardwareUnsupported; } diff --git a/renderdoc/driver/gl/gl_replay_linux.cpp b/renderdoc/driver/gl/gl_replay_linux.cpp index 1070f85f..fef9a3b8 100644 --- a/renderdoc/driver/gl/gl_replay_linux.cpp +++ b/renderdoc/driver/gl/gl_replay_linux.cpp @@ -122,7 +122,7 @@ ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) attribs[i++] = GLX_CONTEXT_PROFILE_MASK_ARB; attribs[i++] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - Display *dpy = XOpenDisplay(NULL); + Display *dpy = RenderDoc::Inst().GetGlobalEnvironment().xlibDisplay; if(dpy == NULL) { @@ -138,7 +138,6 @@ ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) if(fbcfg == NULL) { - XCloseDisplay(dpy); GLReplay::PostContextShutdownCounters(); RDCERR("Couldn't choose default framebuffer config"); return ReplayStatus::APIInitFailed; @@ -177,7 +176,6 @@ ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) if(ctx == NULL || X11ErrorSeen) { XFree(fbcfg); - XCloseDisplay(dpy); GLReplay::PostContextShutdownCounters(); RDCERR("Couldn't create 3.2 context - RenderDoc requires OpenGL 3.2 availability"); return ReplayStatus::APIHardwareUnsupported; @@ -199,7 +197,6 @@ ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) glXDestroyPbufferProc(dpy, pbuffer); glXDestroyCtxProc(dpy, ctx); XFree(fbcfg); - XCloseDisplay(dpy); GLReplay::PostContextShutdownCounters(); RDCERR("Couldn't make pbuffer & context current"); return ReplayStatus::APIInitFailed; @@ -218,7 +215,6 @@ ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) glXDestroyPbufferProc(dpy, pbuffer); glXDestroyCtxProc(dpy, ctx); XFree(fbcfg); - XCloseDisplay(dpy); GLReplay::PostContextShutdownCounters(); return ReplayStatus::APIInitFailed; } @@ -233,7 +229,6 @@ ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) glXDestroyPbufferProc(dpy, pbuffer); glXDestroyCtxProc(dpy, ctx); XFree(fbcfg); - XCloseDisplay(dpy); GLReplay::PostContextShutdownCounters(); return ReplayStatus::APIHardwareUnsupported; } @@ -245,7 +240,6 @@ ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) glXDestroyPbufferProc(dpy, pbuffer); glXDestroyCtxProc(dpy, ctx); XFree(fbcfg); - XCloseDisplay(dpy); GLReplay::PostContextShutdownCounters(); return ReplayStatus::APIHardwareUnsupported; } diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp index 0999f721..23d7dbd9 100644 --- a/renderdoc/replay/entry_points.cpp +++ b/renderdoc/replay/entry_points.cpp @@ -300,6 +300,17 @@ extern "C" RENDERDOC_API const char *RENDERDOC_CC RENDERDOC_GetLogFile() return RDCGETLOGFILE(); } +extern "C" RENDERDOC_API void RENDERDOC_CC +RENDERDOC_InitGlobalEnv(GlobalEnvironment env, const rdctype::array &args) +{ + std::vector argsVec; + argsVec.reserve(args.size()); + for(const rdctype::str &a : args) + argsVec.push_back(a.c_str()); + + RenderDoc::Inst().ProcessGlobalEnvironment(env, argsVec); +} + extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_TriggerExceptionHandler(void *exceptionPtrs, bool32 crashed) { diff --git a/renderdoccmd/renderdoccmd.cpp b/renderdoccmd/renderdoccmd.cpp index 72125a4e..d3727bb8 100644 --- a/renderdoccmd/renderdoccmd.cpp +++ b/renderdoccmd/renderdoccmd.cpp @@ -25,7 +25,6 @@ #include "renderdoccmd.h" #include -#include #include #include @@ -35,6 +34,15 @@ using std::wstring; bool usingKillSignal = false; volatile uint32_t killSignal = false; +rdctype::array convertArgs(const std::vector &args) +{ + rdctype::array ret; + ret.create((int)args.size()); + for(size_t i = 0; i < args.size(); i++) + ret[i] = args[i]; + return ret; +} + void readCapOpts(const std::string &str, CaptureOptions *opts) { if(str.length() < sizeof(CaptureOptions)) @@ -157,6 +165,7 @@ static std::vector version_lines; struct VersionCommand : public Command { + VersionCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) {} virtual const char *Description() { return "Print version information"; } virtual bool IsInternalOnly() { return false; } @@ -187,6 +196,7 @@ void add_version_line(const std::string &str) struct HelpCommand : public Command { + HelpCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) {} virtual const char *Description() { return "Print this help message"; } virtual bool IsInternalOnly() { return false; } @@ -200,6 +210,7 @@ struct HelpCommand : public Command struct ThumbCommand : public Command { + ThumbCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) { parser.set_footer(""); @@ -216,7 +227,8 @@ struct ThumbCommand : public Command virtual bool IsCaptureCommand() { return false; } virtual int Execute(cmdline::parser &parser, const CaptureOptions &) { - if(parser.rest().empty()) + std::vector rest = parser.rest(); + if(rest.empty()) { std::cerr << "Error: thumb command requires a capture filename." << std::endl << std::endl @@ -224,7 +236,11 @@ struct ThumbCommand : public Command return 0; } - string filename = parser.rest()[0]; + string filename = rest[0]; + + rest.erase(rest.begin()); + + RENDERDOC_InitGlobalEnv(m_Env, convertArgs(rest)); string outfile = parser.get("out"); @@ -299,6 +315,7 @@ struct ThumbCommand : public Command struct CaptureCommand : public Command { + CaptureCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) { parser.set_footer(" [program arguments]"); @@ -330,6 +347,8 @@ struct CaptureCommand : public Command cmdLine += EscapeArgument(parser.rest()[i]); } + RENDERDOC_InitGlobalEnv(m_Env, rdctype::array()); + std::cout << "Launching '" << executable << "'"; if(!cmdLine.empty()) @@ -386,6 +405,7 @@ struct CaptureCommand : public Command struct InjectCommand : public Command { + InjectCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) { parser.add("PID", 0, "The process ID of the process to inject.", true); @@ -403,6 +423,8 @@ struct InjectCommand : public Command rdctype::array env; + RENDERDOC_InitGlobalEnv(m_Env, convertArgs(parser.rest())); + uint32_t ident = RENDERDOC_InjectIntoProcess(PID, env, logFile.empty() ? "" : logFile.c_str(), opts, parser.exist("wait-for-exit")); @@ -428,6 +450,7 @@ struct InjectCommand : public Command struct RemoteServerCommand : public Command { + RemoteServerCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) { parser.add("daemon", 'd', "Go into the background."); @@ -447,6 +470,8 @@ struct RemoteServerCommand : public Command string host = parser.get("host"); uint32_t port = parser.get("port"); + RENDERDOC_InitGlobalEnv(m_Env, convertArgs(parser.rest())); + std::cerr << "Spawning a replay host listening on " << (host.empty() ? "*" : host) << ":" << port << "..." << std::endl; @@ -468,6 +493,7 @@ struct RemoteServerCommand : public Command struct ReplayCommand : public Command { + ReplayCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) { parser.set_footer(""); @@ -486,7 +512,8 @@ struct ReplayCommand : public Command virtual bool IsCaptureCommand() { return false; } virtual int Execute(cmdline::parser &parser, const CaptureOptions &) { - if(parser.rest().empty()) + std::vector rest = parser.rest(); + if(rest.empty()) { std::cerr << "Error: capture command requires a filename to load." << std::endl << std::endl @@ -494,7 +521,11 @@ struct ReplayCommand : public Command return 0; } - string filename = parser.rest()[0]; + string filename = rest[0]; + + rest.erase(rest.begin()); + + RENDERDOC_InitGlobalEnv(m_Env, convertArgs(rest)); if(parser.exist("remote-host")) { @@ -572,6 +603,7 @@ struct ReplayCommand : public Command struct CapAltBitCommand : public Command { + CapAltBitCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) { parser.add("pid", 0, ""); @@ -588,6 +620,8 @@ struct CapAltBitCommand : public Command CaptureOptions cmdopts; readCapOpts(parser.get("capopts").c_str(), &cmdopts); + RENDERDOC_InitGlobalEnv(m_Env, rdctype::array()); + std::vector rest = parser.rest(); if(rest.size() % 3 != 0) @@ -673,12 +707,12 @@ struct CapAltBitCommand : public Command } }; -int renderdoccmd(std::vector &argv) +int renderdoccmd(const GlobalEnvironment &env, std::vector &argv) { try { // add basic commands, and common aliases - add_command("version", new VersionCommand()); + add_command("version", new VersionCommand(env)); add_alias("--version", "version"); add_alias("-v", "version"); @@ -686,7 +720,7 @@ int renderdoccmd(std::vector &argv) add_alias("/version", "version"); add_alias("/v", "version"); - add_command("help", new HelpCommand()); + add_command("help", new HelpCommand(env)); add_alias("--help", "help"); add_alias("-h", "help"); @@ -698,12 +732,12 @@ int renderdoccmd(std::vector &argv) add_alias("/?", "help"); // add platform agnostic commands - add_command("thumb", new ThumbCommand()); - add_command("capture", new CaptureCommand()); - add_command("inject", new InjectCommand()); - add_command("remoteserver", new RemoteServerCommand()); - add_command("replay", new ReplayCommand()); - add_command("capaltbit", new CapAltBitCommand()); + add_command("thumb", new ThumbCommand(env)); + add_command("capture", new CaptureCommand(env)); + add_command("inject", new InjectCommand(env)); + add_command("remoteserver", new RemoteServerCommand(env)); + add_command("replay", new ReplayCommand(env)); + add_command("capaltbit", new CapAltBitCommand(env)); if(argv.size() <= 1) { @@ -833,12 +867,12 @@ int renderdoccmd(std::vector &argv) } } -int renderdoccmd(int argc, char **c_argv) +int renderdoccmd(const GlobalEnvironment &env, int argc, char **c_argv) { std::vector argv; argv.resize(argc); for(int i = 0; i < argc; i++) argv[i] = c_argv[i]; - return renderdoccmd(argv); + return renderdoccmd(env, argv); } diff --git a/renderdoccmd/renderdoccmd.h b/renderdoccmd/renderdoccmd.h index 9cd57887..59acb01f 100644 --- a/renderdoccmd/renderdoccmd.h +++ b/renderdoccmd/renderdoccmd.h @@ -24,14 +24,12 @@ #pragma once +#include #include "3rdparty/cmdline/cmdline.h" -struct CaptureOptions; -struct TextureDisplay; -struct IReplayController; - struct Command { + Command(const GlobalEnvironment &env) { m_Env = env; } virtual ~Command() {} virtual void AddOptions(cmdline::parser &parser) = 0; virtual int Execute(cmdline::parser &parser, const CaptureOptions &opts) = 0; @@ -39,6 +37,8 @@ struct Command virtual bool IsInternalOnly() = 0; virtual bool IsCaptureCommand() = 0; + + GlobalEnvironment m_Env; }; extern bool usingKillSignal; @@ -49,8 +49,8 @@ void add_version_line(const std::string &str); void add_command(const std::string &name, Command *cmd); void add_alias(const std::string &alias, const std::string &command); -int renderdoccmd(int argc, char **argv); -int renderdoccmd(std::vector &argv); +int renderdoccmd(const GlobalEnvironment &env, int argc, char **argv); +int renderdoccmd(const GlobalEnvironment &env, std::vector &argv); void readCapOpts(const std::string &str, CaptureOptions *opts); diff --git a/renderdoccmd/renderdoccmd_android.cpp b/renderdoccmd/renderdoccmd_android.cpp index e427b314..10f99aa9 100644 --- a/renderdoccmd/renderdoccmd_android.cpp +++ b/renderdoccmd/renderdoccmd_android.cpp @@ -24,7 +24,6 @@ #include "renderdoccmd.h" #include -#include #include #include #include @@ -116,7 +115,7 @@ void handle_cmd(android_app *app, int32_t cmd) vector args = getRenderdoccmdArgs(); if(!args.size()) break; // Nothing for APK to do. - renderdoccmd(args); + renderdoccmd(GlobalEnvironment(), args); break; } case APP_CMD_TERM_WINDOW: break; diff --git a/renderdoccmd/renderdoccmd_apple.cpp b/renderdoccmd/renderdoccmd_apple.cpp index 5a123ca5..3e5e0478 100644 --- a/renderdoccmd/renderdoccmd_apple.cpp +++ b/renderdoccmd/renderdoccmd_apple.cpp @@ -24,7 +24,6 @@ #include "renderdoccmd.h" #include -#include #include #include #include @@ -48,5 +47,5 @@ int main(int argc, char *argv[]) // process any apple-specific arguments here - return renderdoccmd(argc, argv); + return renderdoccmd(GlobalEnvironment(), argc, argv); } diff --git a/renderdoccmd/renderdoccmd_linux.cpp b/renderdoccmd/renderdoccmd_linux.cpp index 4be601c5..99a129cc 100644 --- a/renderdoccmd/renderdoccmd_linux.cpp +++ b/renderdoccmd/renderdoccmd_linux.cpp @@ -53,7 +53,7 @@ void Daemonise() struct VulkanRegisterCommand : public Command { - VulkanRegisterCommand() {} + VulkanRegisterCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) { parser.add("ignore", 'i', "Do nothing and don't warn about Vulkan layer issues."); @@ -105,7 +105,7 @@ struct VulkanRegisterCommand : public Command } }; -void VerifyVulkanLayer(int argc, char *argv[]) +void VerifyVulkanLayer(const GlobalEnvironment &env, int argc, char *argv[]) { VulkanLayerFlags flags = VulkanLayerFlags::NoFlags; rdctype::array myJSONs; @@ -116,7 +116,7 @@ void VerifyVulkanLayer(int argc, char *argv[]) if(!needUpdate) { if(!(flags & VulkanLayerFlags::Unfixable)) - add_command("vulkanregister", new VulkanRegisterCommand()); + add_command("vulkanregister", new VulkanRegisterCommand(env)); return; } @@ -197,9 +197,11 @@ void VerifyVulkanLayer(int argc, char *argv[]) << std::endl; std::cerr << std::endl; - add_command("vulkanregister", new VulkanRegisterCommand()); + add_command("vulkanregister", new VulkanRegisterCommand(env)); } +static Display *display = NULL; + void DisplayRendererPreview(IReplayController *renderer, TextureDisplay &displayCfg, uint32_t width, uint32_t height) { @@ -210,11 +212,6 @@ void DisplayRendererPreview(IReplayController *renderer, TextureDisplay &display // need to create a hybrid setup xlib and xcb in case only one or the other is supported. // We'll prefer xcb - // call XInitThreads - although we don't use xlib concurrently the driver might need to. - XInitThreads(); - - Display *display = XOpenDisplay(NULL); - if(display == NULL) { std::cerr << "Couldn't open X Display" << std::endl; @@ -373,8 +370,16 @@ int main(int argc, char *argv[]) signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); + GlobalEnvironment env; + + // call XInitThreads - although we don't use xlib concurrently the driver might need to. + XInitThreads(); + + // we don't check if display successfully opened, it's only a problem if it's needed later. + display = env.xlibDisplay = XOpenDisplay(NULL); + #if defined(RENDERDOC_SUPPORT_VULKAN) - VerifyVulkanLayer(argc, argv); + VerifyVulkanLayer(env, argc, argv); #endif // add compiled-in support to version line @@ -444,5 +449,5 @@ int main(int argc, char *argv[]) add_version_line(support); } - return renderdoccmd(argc, argv); + return renderdoccmd(env, argc, argv); } diff --git a/renderdoccmd/renderdoccmd_win32.cpp b/renderdoccmd/renderdoccmd_win32.cpp index 34f54a7a..a8bc510e 100644 --- a/renderdoccmd/renderdoccmd_win32.cpp +++ b/renderdoccmd/renderdoccmd_win32.cpp @@ -26,7 +26,6 @@ #include "renderdoccmd.h" #include #include -#include #include #include #include @@ -281,6 +280,7 @@ void DisplayRendererPreview(IReplayController *renderer, TextureDisplay &display struct UpgradeCommand : public Command { + UpgradeCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) { parser.add("path", 0, ""); } virtual const char *Description() { return "Internal use only!"; } virtual bool IsInternalOnly() { return true; } @@ -488,6 +488,7 @@ struct UpgradeCommand : public Command #if defined(RELEASE) struct CrashHandlerCommand : public Command { + CrashHandlerCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) {} virtual const char *Description() { return "Internal use only!"; } virtual bool IsInternalOnly() { return true; } @@ -673,6 +674,7 @@ struct CrashHandlerCommand : public Command struct GlobalHookCommand : public Command { + GlobalHookCommand(const GlobalEnvironment &env) : Command(env) {} virtual void AddOptions(cmdline::parser &parser) { parser.add("match", 0, ""); @@ -900,18 +902,20 @@ int WINAPI wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInstance, _In_ return 1; } + GlobalEnvironment env; + // perform an upgrade of the UI - add_command("upgrade", new UpgradeCommand()); + add_command("upgrade", new UpgradeCommand(env)); #if defined(RELEASE) // special WIN32 option for launching the crash handler - add_command("crashhandle", new CrashHandlerCommand()); + add_command("crashhandle", new CrashHandlerCommand(env)); #endif // this installs a global windows hook pointing at renderdocshim*.dll that filters all running // processes and loads renderdoc.dll in the target one. In any other process it unloads as soon as // possible - add_command("globalhook", new GlobalHookCommand()); + add_command("globalhook", new GlobalHookCommand(env)); - return renderdoccmd(argv); + return renderdoccmd(env, argv); } -- 2.13.1