diff --git a/renderdoccmd/renderdoccmd_android.cpp b/renderdoccmd/renderdoccmd_android.cpp index 9502a10ff..587792341 100644 --- a/renderdoccmd/renderdoccmd_android.cpp +++ b/renderdoccmd/renderdoccmd_android.cpp @@ -47,11 +47,26 @@ using std::istringstream; struct android_app *android_state; pthread_t cmdthread_handle = 0; -struct +struct PThreadLock { - pthread_mutex_t lock; - pthread_mutexattr_t attr; -} m_DrawLock; + void init() + { + pthread_mutexattr_init(&mutexattr); + pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mutex, &mutexattr); + } + void destroy() + { + pthread_mutex_destroy(&mutex); + pthread_mutexattr_destroy(&mutexattr); + } + bool trylock() { return pthread_mutex_trylock(&mutex) == 0; }; + void lock() { pthread_mutex_lock(&mutex); } + void unlock() { pthread_mutex_unlock(&mutex); } +private: + pthread_mutex_t mutex; + pthread_mutexattr_t mutexattr; +} m_DrawLock, m_CmdLock; void Daemonise() { @@ -60,7 +75,7 @@ void Daemonise() void DisplayGenericSplash() { // if something else is drawing and holding the lock, then bail - if(pthread_mutex_trylock(&m_DrawLock.lock)) + if(!m_DrawLock.trylock()) return; // since we're not pumping this continually and we only draw when we need to, we can just do the @@ -275,7 +290,7 @@ void main() dlclose(libEGL); - pthread_mutex_unlock(&m_DrawLock.lock); + m_DrawLock.unlock(); } WindowingData DisplayRemoteServerPreview(bool active, const rdcarray &systems) @@ -290,11 +305,11 @@ WindowingData DisplayRemoteServerPreview(bool active, const rdcarraywindow; - pthread_mutex_lock(&m_DrawLock.lock); + m_DrawLock.lock(); IReplayOutput *out = renderer->CreateOutput(CreateAndroidWindowingData(connectionScreenWindow), ReplayOutputType::Texture); @@ -331,7 +346,7 @@ void DisplayRendererPreview(IReplayController *renderer, TextureDisplay &display usleep(100000); } - pthread_mutex_unlock(&m_DrawLock.lock); + m_DrawLock.unlock(); } // Returns the renderdoccmd arguments passed via am start @@ -377,7 +392,11 @@ void *cmdthread(void *) { vector args = getRenderdoccmdArgs(); if(args.size()) + { + m_CmdLock.lock(); renderdoccmd(GlobalEnvironment(), args); + m_CmdLock.unlock(); + } // activity is done and should be closed ANativeActivity_finish(android_state->activity); @@ -391,11 +410,26 @@ void handle_cmd(android_app *app, int32_t cmd) { case APP_CMD_INIT_WINDOW: { + // if we already have a thread handle, see if it's still running if(cmdthread_handle != 0) - // If user resumes APK after server shutdown, restart the thread. - pthread_join(cmdthread_handle, NULL); + { + // if the thread isn't running anymore, we can acquire m_CmdLock. If so, we need to join the + // thread and start afresh. If we can't acquire the lock, the thread is still running so we + // leave it alone. + if(m_CmdLock.trylock()) + { + m_CmdLock.unlock(); + // safe to join here, thread will terminate soon if it hasn't already + pthread_join(cmdthread_handle, NULL); + cmdthread_handle = 0; + } + } - pthread_create(&cmdthread_handle, NULL, cmdthread, NULL); + // if we don't have a command thread, start one. + if(cmdthread_handle == 0) + pthread_create(&cmdthread_handle, NULL, cmdthread, NULL); + + DisplayGenericSplash(); break; } case APP_CMD_WINDOW_REDRAW_NEEDED: @@ -413,9 +447,8 @@ void android_main(struct android_app *state) android_state = state; android_state->onAppCmd = handle_cmd; - pthread_mutexattr_init(&m_DrawLock.attr); - pthread_mutexattr_settype(&m_DrawLock.attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&m_DrawLock.lock, &m_DrawLock.attr); + m_DrawLock.init(); + m_CmdLock.init(); ANDROID_LOG("android_main android_state->window: %p", android_state->window); @@ -433,6 +466,6 @@ void android_main(struct android_app *state) ANDROID_LOG("android_main exiting"); - pthread_mutex_destroy(&m_DrawLock.lock); - pthread_mutexattr_destroy(&m_DrawLock.attr); + m_DrawLock.destroy(); + m_CmdLock.destroy(); }