diff --git a/qrenderdoc/Windows/Dialogs/LiveCapture.cpp b/qrenderdoc/Windows/Dialogs/LiveCapture.cpp index ac7a90159..a5c8687b4 100644 --- a/qrenderdoc/Windows/Dialogs/LiveCapture.cpp +++ b/qrenderdoc/Windows/Dialogs/LiveCapture.cpp @@ -122,6 +122,7 @@ LiveCapture::LiveCapture(ICaptureContext &ctx, const QString &hostname, const QS ui->triggerDelayedCapture->setEnabled(false); ui->triggerImmediateCapture->setEnabled(false); ui->queueCap->setEnabled(false); + ui->cycleActiveWindow->setEnabled(false); ui->target->setText(QString()); @@ -282,6 +283,11 @@ void LiveCapture::on_triggerImmediateCapture_clicked() m_CaptureNumFrames = (int)ui->numFrames->value(); } +void LiveCapture::on_cycleActiveWindow_clicked() +{ + m_Connection->CycleActiveWindow(); +} + void LiveCapture::on_triggerDelayedCapture_clicked() { if(ui->captureDelay->value() == 0.0) @@ -1257,6 +1263,12 @@ void LiveCapture::connectionThreadEntry() } } } + + if(msg.type == TargetControlMessageType::CapturableWindowCount) + { + uint32_t windows = msg.capturableWindowCount; + GUIInvoke::call(this, [this, windows]() { ui->cycleActiveWindow->setEnabled(windows > 1); }); + } } GUIInvoke::call(this, [this]() { @@ -1269,6 +1281,7 @@ void LiveCapture::connectionThreadEntry() ui->triggerDelayedCapture->setEnabled(false); ui->triggerImmediateCapture->setEnabled(false); ui->queueCap->setEnabled(false); + ui->cycleActiveWindow->setEnabled(false); ui->apiStatus->setText(tr("None")); ui->apiIcon->setVisible(false); diff --git a/qrenderdoc/Windows/Dialogs/LiveCapture.h b/qrenderdoc/Windows/Dialogs/LiveCapture.h index 35adfc518..32aa8d8a0 100644 --- a/qrenderdoc/Windows/Dialogs/LiveCapture.h +++ b/qrenderdoc/Windows/Dialogs/LiveCapture.h @@ -70,6 +70,7 @@ private slots: void on_captures_itemActivated(QListWidgetItem *item); void on_childProcesses_itemActivated(QListWidgetItem *item); void on_triggerImmediateCapture_clicked(); + void on_cycleActiveWindow_clicked(); void on_triggerDelayedCapture_clicked(); void on_queueCap_clicked(); void on_previewSplit_splitterMoved(int pos, int index); diff --git a/qrenderdoc/Windows/Dialogs/LiveCapture.ui b/qrenderdoc/Windows/Dialogs/LiveCapture.ui index b7cba0995..58d10eb9c 100644 --- a/qrenderdoc/Windows/Dialogs/LiveCapture.ui +++ b/qrenderdoc/Windows/Dialogs/LiveCapture.ui @@ -190,7 +190,14 @@ Tools - + + + + Capture Frame(s) Immediately + + + + @@ -212,7 +219,7 @@ - + Frame @@ -225,14 +232,14 @@ - + Capture After Delay: - + Capture Specific Frame(s): @@ -267,7 +274,7 @@ - + Qt::Vertical @@ -280,10 +287,10 @@ - - + + - Capture Frame(s) Immediately + Cycle Active Window diff --git a/renderdoc/api/replay/control_types.h b/renderdoc/api/replay/control_types.h index fa05c0ea4..1aca56204 100644 --- a/renderdoc/api/replay/control_types.h +++ b/renderdoc/api/replay/control_types.h @@ -542,6 +542,9 @@ When valid, will be in the range of 0.0 to 1.0 (0 - 100%). If not valid when a c or has finished, it will be -1.0 )"); float capProgress = -1.0f; + + DOCUMENT("The number of the capturable windows"); + uint32_t capturableWindowCount = 0; }; DECLARE_REFLECTION_STRUCT(TargetControlMessage); diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index cc40325cd..d964a7b10 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -1342,6 +1342,9 @@ The details of the types of messages that can be received are listed under )"); virtual TargetControlMessage ReceiveMessage(RENDERDOC_ProgressCallback progress) = 0; + DOCUMENT("Cycle the currently active window if there are more windows to capture."); + virtual void CycleActiveWindow() = 0; + protected: ITargetControl() = default; ~ITargetControl() = default; diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 7a2c39b9f..5c5dd418e 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -3143,6 +3143,7 @@ enum class TargetControlMessageType : uint32_t RegisterAPI, NewChild, CaptureProgress, + CapturableWindowCount }; DECLARE_REFLECTION_ENUM(TargetControlMessageType); diff --git a/renderdoc/core/core.cpp b/renderdoc/core/core.cpp index 378953f51..3bf1bce50 100644 --- a/renderdoc/core/core.cpp +++ b/renderdoc/core/core.cpp @@ -542,27 +542,7 @@ void RenderDoc::Tick() if(!prev_focus && cur_focus) { - m_Cap = 0; - - // can only shift focus if we have multiple windows - if(m_WindowFrameCapturers.size() > 1) - { - for(auto it = m_WindowFrameCapturers.begin(); it != m_WindowFrameCapturers.end(); ++it) - { - if(it->first == m_ActiveWindow) - { - auto nextit = it; - ++nextit; - - if(nextit != m_WindowFrameCapturers.end()) - m_ActiveWindow = nextit->first; - else - m_ActiveWindow = m_WindowFrameCapturers.begin()->first; - - break; - } - } - } + CycleActiveWindow(); } if(!prev_cap && cur_cap) { @@ -573,6 +553,31 @@ void RenderDoc::Tick() prev_cap = cur_cap; } +void RenderDoc::CycleActiveWindow() +{ + m_Cap = 0; + + // can only shift focus if we have multiple windows + if(m_WindowFrameCapturers.size() > 1) + { + for(auto it = m_WindowFrameCapturers.begin(); it != m_WindowFrameCapturers.end(); ++it) + { + if(it->first == m_ActiveWindow) + { + auto nextit = it; + ++nextit; + + if(nextit != m_WindowFrameCapturers.end()) + m_ActiveWindow = nextit->first; + else + m_ActiveWindow = m_WindowFrameCapturers.begin()->first; + + break; + } + } + } +} + string RenderDoc::GetOverlayText(RDCDriver driver, uint32_t frameNumber, int flags) { const bool activeWindow = (flags & eOverlay_ActiveWindow); diff --git a/renderdoc/core/core.h b/renderdoc/core/core.h index fb85a3700..b0ac732b8 100644 --- a/renderdoc/core/core.h +++ b/renderdoc/core/core.h @@ -536,6 +536,8 @@ public: string GetOverlayText(RDCDriver driver, uint32_t frameNumber, int flags); + void CycleActiveWindow(); + uint32_t GetCapturableWindowCount() { return (uint32_t)m_WindowFrameCapturers.size(); } private: RenderDoc(); ~RenderDoc(); diff --git a/renderdoc/core/target_control.cpp b/renderdoc/core/target_control.cpp index 2be440fd3..bcf83ac74 100644 --- a/renderdoc/core/target_control.cpp +++ b/renderdoc/core/target_control.cpp @@ -30,7 +30,7 @@ #include "os/os_specific.h" #include "serialise/serialiser.h" -static const uint32_t TargetControlProtocolVersion = 3; +static const uint32_t TargetControlProtocolVersion = 4; static bool IsProtocolVersionSupported(const uint32_t protocolVersion) { @@ -38,6 +38,10 @@ static bool IsProtocolVersionSupported(const uint32_t protocolVersion) if(protocolVersion == 2) return true; + // 3 -> 4 added active window cycle and window count packets + if(protocolVersion == 3) + return true; + if(protocolVersion == TargetControlProtocolVersion) return true; @@ -57,6 +61,8 @@ enum PacketType : uint32_t ePacket_QueueCapture, ePacket_NewChild, ePacket_CaptureProgress, + ePacket_CycleActiveWindow, + ePacket_CapturableWindowCount }; DECLARE_REFLECTION_ENUM(PacketType); @@ -77,6 +83,8 @@ std::string DoStringise(const PacketType &el) STRINGISE_ENUM_NAMED(ePacket_QueueCapture, "Queue Capture"); STRINGISE_ENUM_NAMED(ePacket_NewChild, "New Child"); STRINGISE_ENUM_NAMED(ePacket_CaptureProgress, "Capture Progress"); + STRINGISE_ENUM_NAMED(ePacket_CycleActiveWindow, "Cycle Active Window"); + STRINGISE_ENUM_NAMED(ePacket_CapturableWindowCount, "Capturable Window Count"); } END_ENUM_STRINGISE(); } @@ -131,6 +139,7 @@ void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *cli std::vector > children; std::map drivers; float prevCaptureProgress = captureProgress; + uint32_t prevWindows = 0; while(client) { @@ -148,6 +157,8 @@ void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *cli std::vector caps = RenderDoc::Inst().GetCaptures(); std::vector > childprocs = RenderDoc::Inst().GetChildProcesses(); + uint32_t curWindows = RenderDoc::Inst().GetCapturableWindowCount(); + if(curdrivers != drivers) { // find the first difference, either a new key or a key with a different value, and send it. @@ -242,6 +253,16 @@ void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *cli } } } + else if(version >= 4 && prevWindows != curWindows) + { + prevWindows = curWindows; + + WRITE_DATA_SCOPE(); + { + SCOPED_SERIALISE_CHUNK(ePacket_CapturableWindowCount); + SERIALISE_ELEMENT(curWindows); + } + } if(curtime > pingtime) { @@ -321,6 +342,10 @@ void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *cli RenderDoc::Inst().MarkCaptureRetrieved(id); } } + else if(type == ePacket_CycleActiveWindow) + { + RenderDoc::Inst().CycleActiveWindow(); + } reader.EndChunk(); @@ -602,6 +627,18 @@ public: SAFE_DELETE(m_Socket); } + void CycleActiveWindow() + { + if(m_Version < 4) + return; + + WRITE_DATA_SCOPE(); + SCOPED_SERIALISE_CHUNK(ePacket_CycleActiveWindow); + + if(ser.IsErrored()) + SAFE_DELETE(m_Socket); + } + TargetControlMessage ReceiveMessage(RENDERDOC_ProgressCallback progress) { TargetControlMessage msg; @@ -778,6 +815,16 @@ public: reader.EndChunk(); return msg; } + else if(type == ePacket_CapturableWindowCount) + { + msg.type = TargetControlMessageType::CapturableWindowCount; + uint32_t windows = 0; + READ_DATA_SCOPE(); + SERIALISE_ELEMENT(windows); + msg.capturableWindowCount = windows; + reader.EndChunk(); + return msg; + } else { RDCERR("Unexpected packed received: %d", type);