feat(activex): present EGFX dirty regions - #1874
feat(activex): present EGFX dirty regions#1874Marc-André Moreau (mamoreau-devolutions) wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds dirty-region delivery for ActiveX while retaining full-frame fallback.
Changes:
- Propagates validated EGFX reset extents into session framebuffers.
- Adds packed desktop updates and retained partial-frame presentation.
- Introduces bounded damage queuing and related tests/documentation.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
crates/ironrdp-testsuite-extra/tests/client/output_channel.rs |
Tests desktop-update validation. |
crates/ironrdp-session/src/active_stage.rs |
Resizes framebuffers after EGFX resets. |
crates/ironrdp-egfx/src/compositor.rs |
Validates output dimensions and memory limits. |
crates/ironrdp-egfx/src/client.rs |
Reports validated reset extents. |
crates/ironrdp-client/src/rdp.rs |
Adds packed dirty-region delivery. |
crates/ironrdp-activex/src/rpc.rs |
Applies partial updates to retained RPC frames. |
crates/ironrdp-activex/src/control.rs |
Queues, merges, presents, and invalidates dirty regions. |
crates/ironrdp-activex/README.md |
Documents the dirty-region pipeline. |
|
This pull request is Please split it into focused pull requests that can each be reviewed on their own. When the parts build on each other, stacked pull requests let you open each one on top of the last without waiting for the one below to merge. Stacks require every branch to live in this repository, so from a fork, please open separate pull requests instead. Automated review resumes once the change is below the |
|
The Note Human-tuned, LLM-assisted content. |
18e915a to
36a08cb
Compare
Propagate validated ResetGraphics extents into the session framebuffer and deliver packed desktop damage to ActiveX without rebuilding full image snapshots. Coalesce only fully covered regions, preserve disjoint updates with bounded backpressure, and update retained GDI and RPC surfaces in place. Keep V8 non-AVC negotiation and full-frame output fallback unchanged.
Destroy prior surfaces when a ResetGraphics output exceeds local allocation limits, matching protocol reset semantics. Notify handlers about the rejected output so capture replay retains its unsupported-path classification and fuzz models stay synchronized.
Preserve exact compositor regions so sparse updates do not expand into full bounding-box copies, and cap queued pixel payloads at 256 MiB with backpressure. Retain software cursor shape, position, and visibility when ResetGraphics replaces the session framebuffer.
Invalidate retained RPC frames when a resized desktop exceeds the screenshot budget, and consume the EGFX client's accepted reset state directly during capture replay.
Keep exact frame and static-channel updates ordered when the UI queue is saturated, and make dispatch recovery fail instead of waiting without an outstanding message. Reuse framebuffer storage across graphics resets and clip retained software cursors without source-rectangle underflow.
Integrate partial frame presentation with the modern screen-update suspension contract by snapshotting one bounded full-frame base and applying every suspended dirty region before resume.
36a08cb to
4091362
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Direct frame dispatch can violate lifecycle ordering, and differing framebuffer extents still evict accepted updates.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 11/11 changed files
- Comments generated: 2
- Review effort level: Balanced
| let client = RdpClient::new(config, output_sender).with_desktop_update_handler(move |update| { | ||
| let _ = queue_worker_event( | ||
| &desktop_update_events, | ||
| &desktop_update_posted, | ||
| HWND(desktop_update_hwnd as *mut c_void), | ||
| WorkerEvent::Image { |
| if !same_extent { | ||
| queue[index] = event; | ||
| true |
Propagate validated ResetGraphics extents into the session framebuffer and deliver exact packed desktop damage to ActiveX without rebuilding full image snapshots.
Coalesce only fully covered regions, preserve sparse updates with a 64-event and 256 MiB pixel-data budget, and backpressure without evicting accepted frame or static-channel payloads. Update retained GDI and RPC surfaces in place. Reuse framebuffer storage with fallible growth, and retain software cursor shape, position, visibility, and clipping across graphics resets. Keep V8 non-AVC negotiation and full-frame output fallback unchanged. Rejected oversized resets still destroy prior surfaces and are reported as unsupported without allocating a session framebuffer.