Skip to content

feat(egfx): add send_clearcodec_frame for server-side ClearCodec transmission - #1195

Closed
Greg Lamberson (glamberson) wants to merge 2 commits into
Devolutions:masterfrom
lamco-admin:feat/clearcodec-server-send
Closed

Greg Lamberson (glamberson) wants to merge 2 commits into
Devolutions:masterfrom
lamco-admin:feat/clearcodec-server-send

Conversation

@glamberson

Copy link
Copy Markdown
Contributor

Depends on #1174.

Summary

Add GraphicsPipelineServer::send_clearcodec_frame() to queue pre-encoded ClearCodec bitmap streams for transmission via WireToSurface1. Follows the same pattern as send_avc420_frame and send_uncompressed_frame with QoE backpressure tracking.

Changes

1 file, 46 lines in ironrdp-egfx/src/server.rs.

Test plan

  • All 5 xtask gates pass
  • Pattern matches existing send_avc420_frame / send_uncompressed_frame

Add ClearCodec (MS-RDPEGFX 2.2.4.1) codec support across two crates:

ironrdp-pdu: Wire-format decode/encode for all ClearCodec layers
(residual BGR RLE, bands with V-bar caching, subcodec dispatch
including RLEX palette-indexed RLE). Full round-trip test coverage.

ironrdp-graphics: ClearCodecDecoder with persistent V-bar and glyph
caches. ClearCodecEncoder with residual-only encoding and glyph
deduplication for server-side bitmap compression.
…smission

Add GraphicsPipelineServer::send_clearcodec_frame() to queue pre-encoded
ClearCodec bitmap streams for transmission via WireToSurface1. Follows
the same pattern as send_avc420_frame and send_uncompressed_frame with
QoE backpressure tracking.
@glamberson

Copy link
Copy Markdown
Contributor Author

Closing as superseded by #1175. The 46-line `GraphicsPipelineServer::send_clearcodec_frame()` helper that this PR was opened to add is already present byte-for-byte in #1175 at `crates/ironrdp-egfx/src/server.rs`, alongside the client-side ClearCodec decode dispatch the same #1175 introduces. Both PRs were authored on 2026-04-01 and the helper landed in both copies; this one never got closed after the consolidation.

#1175 currently sits on the amended #1174 head (`6e142c37`) with the dimension-cap / overflow / alpha-contract hardening fixes applied from earlier today, plus the RLEX stop_index validation and the glyph-dimension check added during its own review cycle. Nothing in this PR is missing from #1175.

No code change to land; just a closure.

Marc-André Moreau (mamoreau-devolutions) pushed a commit that referenced this pull request Jul 30, 2026
Follow-up to #1174. Supersedes #1195 (the standalone server-helper PR;
its 46-line `send_clearcodec_frame()` is included here).

Wires ClearCodec into the EGFX client's WireToSurface1 codec dispatch,
matching the existing AVC420 and Uncompressed decode patterns.

Changes:
- ClearCodecDecoder field on GraphicsPipelineClient (always enabled,
  pure Rust, no external codec dependency). Constructed eagerly in
  GraphicsPipelineClient::new(), so V-bar (32K full + 16K short
  entries) and glyph (4000 entries) ring buffers are allocated up
  front regardless of whether ClearCodec frames are subsequently
  received.
- Codec1Type::ClearCodec arm decodes bitmap data and converts BGRA
  output to RGBA for the uniform BitmapUpdate pixel format
- ResetGraphics does NOT reset the ClearCodec decoder. Per MS-RDPEGFX
  3.3.5.14 it only resizes the Graphics Output Buffer; cache lifetime
  is driven by the stream through CLEARCODEC_FLAG_CACHE_RESET
  (2.2.4.1), which the decoder already honors by resetting the V-bar
  cursors. Dropping the decoder there would also drop the glyph cache
  and break legitimate post-reset GLYPH_HITs.
- GraphicsPipelineServer::send_clearcodec_frame() helper for
  symmetric server-side use (mirrors send_avc420_frame /
  send_avc444_frame pattern, including QoE backpressure recording)
- 4 integration tests (basic decode, RGBA output verification,
  glyph-cache survival across ResetGraphics, glyph-hit reshape)
- 1 unit test for BGRA-to-RGBA channel reordering

Two decoder corrections from review. Both land in code introduced
by #1174, since the defects are there rather than in the dispatch:

- ClearCodecDecoder::decode required a glyph hit's destination
  dimensions to match the cached entry exactly. Per MS-RDPEGFX 4.1.1.5
  a glyph is a dimensionless linear pixel stream, so any destination
  rectangle of the same area is valid (cached 2x8, hit 4x4). The check
  now compares pixel count.
- The RLEX segment decoder clamped an out-of-range suite with
  saturating_sub, rendering a shorter suite instead of rejecting the
  stream. Per MS-RDPEGFX 2.2.4.1.1.3.1.1.2 startIndex is
  stopIndex - suiteDepth and must itself be a palette entry, so it now
  returns a decode error.

Unlike H.264 which requires an external decoder via the H264Decoder
trait, ClearCodec is pure Rust (ironrdp-graphics).

Part of #1464.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants