/****************************************************************************** * The MIT License (MIT) * * Copyright (c) 2019-2022 Baldur Karlsson * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. ******************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include #include "Interface/QRDInterface.h" #include "QRDUtils.h" struct IReplayController; class LambdaThread; class RemoteHost; class ReplayManager : public IReplayManager { Q_DECLARE_TR_FUNCTIONS(ReplayManager); public: ReplayManager(); ~ReplayManager(); void OpenCapture(const QString &capturefile, const ReplayOptions &opts, RENDERDOC_ProgressCallback progress); void DeleteCapture(const rdcstr &capturefile, bool local); bool IsRunning(); ResultDetails GetCreateStatus() { return m_CreateResult; } void SetFatalErrorCallback(std::function cb) { m_FatalErrorCallback = cb; } ResultDetails GetFatalError() { return m_FatalError; } float GetCurrentProcessingTime(); QString GetCurrentProcessingTag(); // this tagged version is for cases when we might send a request - e.g. to pick a vertex or pixel // - and want to pre-empt it with a new request before the first has returned. Either because some // other work is taking a while or because we're sending requests faster than they can be // processed. // the manager processes only the request on the top of the queue, so when a new tagged invoke // comes in, we remove any other requests in the queue before it that have the same tag void AsyncInvoke(const rdcstr &tag, InvokeCallback m); void AsyncInvoke(InvokeCallback m); void BlockInvoke(InvokeCallback m); void CancelReplayLoop(); void CloseThread(); ResultDetails ConnectToRemoteServer(RemoteHost host); void DisconnectFromRemoteServer(); void ShutdownServer(); void PingRemote(); ICaptureAccess *GetCaptureAccess() { if(m_Remote) return m_Remote; if(m_CaptureFile) return m_CaptureFile; return NULL; } // may return NULL if the capture file is not open locally. Consider using ICaptureAccess above to // work whether local or remote. ICaptureFile *GetCaptureFile() { return m_CaptureFile; } void ReopenCaptureFile(const QString &path); RemoteHost CurrentRemote() { return m_RemoteHost; } ExecuteResult ExecuteAndInject(const rdcstr &exe, const rdcstr &workingDir, const rdcstr &cmdLine, const rdcarray &env, const rdcstr &capturefile, CaptureOptions opts); rdcarray GetRemoteSupport(); void GetHomeFolder(bool synchronous, DirectoryBrowseCallback cb); void ListFolder(const rdcstr &path, bool synchronous, DirectoryBrowseCallback cb); rdcstr CopyCaptureToRemote(const rdcstr &localpath, QWidget *window); void CopyCaptureFromRemote(const rdcstr &remotepath, const rdcstr &localpath, QWidget *window); private: struct InvokeHandle { InvokeHandle(InvokeCallback m, const QString &t = QString()) { tag = t; method = m; selfdelete = false; } QString tag; InvokeCallback method; QSemaphore processed; bool selfdelete; }; void run(int proxyRenderer, const QString &capturefile, const ReplayOptions &opts, RENDERDOC_ProgressCallback progress); QMutex m_TimerLock; QElapsedTimer m_CommandTimer; QString m_CommandTag; QMutex m_RenderLock; QQueue m_RenderQueue; QWaitCondition m_RenderCondition; ICaptureFile *m_CaptureFile = NULL; IReplayController *m_Renderer = NULL; void PushInvoke(InvokeHandle *cmd); QMutex m_RemoteLock; RemoteHost m_RemoteHost; IRemoteServer *m_Remote = NULL; IRemoteServer *m_OrphanedRemote = NULL; std::function m_FatalErrorCallback; ResultDetails m_FatalError = {ResultCode::Succeeded}; volatile bool m_Running; LambdaThread *m_Thread; ResultDetails m_CreateResult = {ResultCode::Succeeded}; };