Skip to content

Commit 082754a

Browse files
lamco-officeclaude
andcommitted
feat(egfx): add MS-RDPEGFX Graphics Pipeline Extension
Add complete MS-RDPEGFX implementation with PDU types and server logic. PDU layer (based on work by @elmarco in #648): - All 23 RDPGFX PDUs (WireToSurface, CreateSurface, ResetGraphics, etc.) - Capability sets V8 through V10.7 - AVC420/AVC444 bitmap stream codecs - Timestamp, QuantQuality, and supporting types Server implementation: - Multi-surface management (Offscreen Surfaces ADM element) - Frame tracking with flow control (Unacknowledged Frames ADM element) - V8/V8.1/V10/V10.1-V10.7 capability negotiation - AVC420 and AVC444 frame sending - QoE metrics processing - Cache import handling - Resize coordination - Backpressure via client queue depth Client-side DVC processor (from #648): - Basic message processing scaffolding Credits: @elmarco for PDU definitions and protocol research in PR #648. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent b50b648 commit 082754a

File tree

13 files changed

+4457
-0
lines changed

13 files changed

+4457
-0
lines changed

Cargo.lock

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ironrdp-egfx/CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [0.1.0] - 2024-XX-XX
9+
10+
### Added
11+
12+
- Initial release
13+
- MS-RDPEGFX PDU types (all 23 PDUs)
14+
- Client-side DVC processor
15+
- Server-side implementation with:
16+
- Multi-surface management (Offscreen Surfaces ADM element)
17+
- Frame tracking with flow control (Unacknowledged Frames ADM element)
18+
- V8/V8.1/V10/V10.1-V10.7 capability negotiation
19+
- AVC420 and AVC444 frame sending
20+
- QoE metrics processing
21+
- Cache import handling
22+
- Resize coordination

crates/ironrdp-egfx/Cargo.toml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[package]
2+
name = "ironrdp-egfx"
3+
version = "0.1.0"
4+
readme = "README.md"
5+
description = "Graphics pipeline dynamic channel extension implementation"
6+
edition.workspace = true
7+
license.workspace = true
8+
homepage.workspace = true
9+
repository.workspace = true
10+
authors.workspace = true
11+
keywords.workspace = true
12+
categories.workspace = true
13+
14+
[lib]
15+
doctest = false
16+
# test = false
17+
18+
[dependencies]
19+
bit_field = "0.10"
20+
bitflags = "2.4"
21+
ironrdp-core = { path = "../ironrdp-core", version = "0.1" } # public
22+
ironrdp-dvc = { path = "../ironrdp-dvc", version = "0.4" } # public
23+
ironrdp-graphics = { path = "../ironrdp-graphics", version = "0.6" } # public
24+
ironrdp-pdu = { path = "../ironrdp-pdu", version = "0.6" } # public
25+
tracing = { version = "0.1", features = ["log"] }
26+
27+
[lints]
28+
workspace = true

crates/ironrdp-egfx/LICENSE-APACHE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../LICENSE-APACHE

crates/ironrdp-egfx/LICENSE-MIT

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../LICENSE-MIT

crates/ironrdp-egfx/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# ironrdp-egfx
2+
3+
Graphics Pipeline Extension ([MS-RDPEGFX]) implementation for IronRDP.
4+
5+
Provides PDU types and client/server processors for the Display Pipeline Virtual
6+
Channel Extension, including H.264/AVC420 and AVC444 video streaming support.
7+
8+
[MS-RDPEGFX]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegfx/da5c75f9-cd99-450c-98c4-014a496942b0

crates/ironrdp-egfx/src/client.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use ironrdp_core::{impl_as_any, ReadCursor};
2+
use ironrdp_dvc::{DvcClientProcessor, DvcMessage, DvcProcessor};
3+
use ironrdp_graphics::zgfx;
4+
use ironrdp_pdu::{decode_cursor, decode_err, PduResult};
5+
use tracing::trace;
6+
7+
use crate::{
8+
pdu::{CapabilitiesAdvertisePdu, CapabilitiesV8Flags, CapabilitySet, GfxPdu},
9+
CHANNEL_NAME,
10+
};
11+
12+
pub trait GraphicsPipelineHandler: Send {
13+
fn capabilities(&self) -> Vec<CapabilitySet> {
14+
vec![CapabilitySet::V8 {
15+
flags: CapabilitiesV8Flags::empty(),
16+
}]
17+
}
18+
19+
fn handle_pdu(&mut self, pdu: GfxPdu) {
20+
trace!(?pdu);
21+
}
22+
}
23+
24+
/// A client for the Graphics Pipeline Virtual Channel.
25+
pub struct GraphicsPipelineClient {
26+
handler: Box<dyn GraphicsPipelineHandler>,
27+
decompressor: zgfx::Decompressor,
28+
decompressed_buffer: Vec<u8>,
29+
}
30+
31+
impl GraphicsPipelineClient {
32+
pub fn new(handler: Box<dyn GraphicsPipelineHandler>) -> Self {
33+
Self {
34+
handler,
35+
decompressor: zgfx::Decompressor::new(),
36+
decompressed_buffer: Vec::with_capacity(1024 * 16),
37+
}
38+
}
39+
}
40+
41+
impl_as_any!(GraphicsPipelineClient);
42+
43+
impl DvcProcessor for GraphicsPipelineClient {
44+
fn channel_name(&self) -> &str {
45+
CHANNEL_NAME
46+
}
47+
48+
fn start(&mut self, _channel_id: u32) -> PduResult<Vec<DvcMessage>> {
49+
let pdu = GfxPdu::CapabilitiesAdvertise(CapabilitiesAdvertisePdu(self.handler.capabilities()));
50+
51+
Ok(vec![Box::new(pdu)])
52+
}
53+
54+
fn process(&mut self, _channel_id: u32, payload: &[u8]) -> PduResult<Vec<DvcMessage>> {
55+
self.decompressed_buffer.clear();
56+
self.decompressor
57+
.decompress(payload, &mut self.decompressed_buffer)
58+
.map_err(|e| decode_err!(e))?;
59+
60+
let mut cursor = ReadCursor::new(self.decompressed_buffer.as_slice());
61+
while !cursor.is_empty() {
62+
let pdu = decode_cursor(&mut cursor).map_err(|e| decode_err!(e))?;
63+
self.handler.handle_pdu(pdu);
64+
}
65+
66+
Ok(vec![])
67+
}
68+
}
69+
70+
impl DvcClientProcessor for GraphicsPipelineClient {}

crates/ironrdp-egfx/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![cfg_attr(doc, doc = include_str!("../README.md"))]
2+
#![doc(html_logo_url = "https://cdnweb.devolutions.net/images/projects/devolutions/logos/devolutions-icon-shadow.svg")]
3+
4+
pub const CHANNEL_NAME: &str = "Microsoft::Windows::RDS::Graphics";
5+
6+
pub mod client;
7+
pub mod pdu;
8+
pub mod server;

0 commit comments

Comments
 (0)