diff --git a/idd/LGIdd/LGIdd.vcxproj b/idd/LGIdd/LGIdd.vcxproj
index 010591c2..7a52074a 100644
--- a/idd/LGIdd/LGIdd.vcxproj
+++ b/idd/LGIdd/LGIdd.vcxproj
@@ -121,6 +121,7 @@
+
diff --git a/idd/LGIdd/LGIdd.vcxproj.filters b/idd/LGIdd/LGIdd.vcxproj.filters
index 32759f45..ea027eb0 100644
--- a/idd/LGIdd/LGIdd.vcxproj.filters
+++ b/idd/LGIdd/LGIdd.vcxproj.filters
@@ -175,6 +175,9 @@
Transport
+
+ Transport
+
Transport
diff --git a/idd/LGIdd/transport/FrameProfile.h b/idd/LGIdd/transport/FrameProfile.h
new file mode 100644
index 00000000..7d0bdf51
--- /dev/null
+++ b/idd/LGIdd/transport/FrameProfile.h
@@ -0,0 +1,162 @@
+/**
+ * Looking Glass
+ * Copyright © 2017-2026 The Looking Glass Authors
+ * https://looking-glass.io
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#pragma once
+
+#include
+#include
+
+enum class FrameStorage : uint8_t
+{
+ D3D12_TEXTURE,
+ D3D11_TEXTURE,
+};
+
+enum class GpuMode : uint8_t
+{
+ HARDWARE,
+ SOFTWARE,
+};
+
+enum class FramePixel : uint8_t
+{
+ BGRA8,
+ RGBA8,
+ RGB10A2,
+ RGBA16F,
+};
+
+enum class FrameSignal : uint8_t
+{
+ SRGB,
+ PQ_BT2020,
+ SCRGB_LINEAR,
+};
+
+struct FrameProfile
+{
+ // Transport frame inputs are always Direct3D textures.
+ FrameStorage storage = FrameStorage::D3D12_TEXTURE;
+ FramePixel pixel = FramePixel::BGRA8;
+ FrameSignal signal = FrameSignal::SRGB;
+};
+
+struct FrameCfg
+{
+ // Software mode still provides a Direct3D texture to the transport.
+ GpuMode mode = GpuMode::HARDWARE;
+ LUID adapter = {};
+ unsigned width = 0;
+ unsigned height = 0;
+ FrameProfile profile;
+};
+
+namespace Frame
+{
+ inline bool Same(const LUID& left, const LUID& right)
+ {
+ return left.LowPart == right.LowPart &&
+ left.HighPart == right.HighPart;
+ }
+
+ inline bool Same(const FrameProfile& left, const FrameProfile& right)
+ {
+ return left.storage == right.storage &&
+ left.pixel == right.pixel &&
+ left.signal == right.signal;
+ }
+
+ inline bool Same(const FrameCfg& left, const FrameCfg& right)
+ {
+ return
+ left.mode == right.mode &&
+ Same(left.adapter, right.adapter) &&
+ left.width == right.width &&
+ left.height == right.height &&
+ Same(left.profile, right.profile);
+ }
+
+ inline bool Valid(GpuMode mode)
+ {
+ return mode == GpuMode::HARDWARE || mode == GpuMode::SOFTWARE;
+ }
+
+ inline bool Valid(FrameStorage storage)
+ {
+ return storage == FrameStorage::D3D12_TEXTURE ||
+ storage == FrameStorage::D3D11_TEXTURE;
+ }
+
+ inline bool Valid(FramePixel pixel, FrameSignal signal)
+ {
+ switch (signal)
+ {
+ case FrameSignal::SRGB:
+ return pixel == FramePixel::BGRA8 || pixel == FramePixel::RGBA8;
+
+ case FrameSignal::SCRGB_LINEAR:
+ return pixel == FramePixel::RGBA16F;
+
+ case FrameSignal::PQ_BT2020:
+ return pixel == FramePixel::RGB10A2;
+ }
+ return false;
+ }
+
+ inline bool Valid(const FrameProfile& profile)
+ {
+ return Valid(profile.storage) && Valid(profile.pixel, profile.signal);
+ }
+
+ inline bool Can(FrameSignal source, FrameSignal target)
+ {
+ switch (source)
+ {
+ case FrameSignal::SRGB:
+ return target == FrameSignal::SRGB;
+
+ case FrameSignal::SCRGB_LINEAR:
+ return target == FrameSignal::SCRGB_LINEAR ||
+ target == FrameSignal::PQ_BT2020;
+
+ case FrameSignal::PQ_BT2020:
+ return target == FrameSignal::PQ_BT2020;
+ }
+ return false;
+ }
+
+ inline FrameProfile Store(
+ const FrameProfile& profile, FrameStorage storage)
+ {
+ FrameProfile result = profile;
+ result.storage = storage;
+ return result;
+ }
+}
+
+enum class CfgResult : uint8_t
+{
+ ACCEPTED,
+ // The transport declined this profile and permits another candidate.
+ NEXT,
+ REJECTED,
+ RETRY,
+ FAILED,
+};
diff --git a/idd/LGIdd/transport/ITransport.h b/idd/LGIdd/transport/ITransport.h
index c3913fca..a4d5bb60 100644
--- a/idd/LGIdd/transport/ITransport.h
+++ b/idd/LGIdd/transport/ITransport.h
@@ -22,6 +22,7 @@
#include "transport/DirectFrameBufferMemory.h"
#include "transport/FrameCaps.h"
+#include "transport/FrameProfile.h"
#include "transport/TransportConfig.h"
#include