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