Skip to content

fix(graphics): retain Progressive difference tiles - #1698

Open
Marc-André Moreau (mamoreau-devolutions) wants to merge 3 commits into
masterfrom
copilot/retain-progressive-difference-tiles
Open

fix(graphics): retain Progressive difference tiles#1698
Marc-André Moreau (mamoreau-devolutions) wants to merge 3 commits into
masterfrom
copilot/retain-progressive-difference-tiles

Conversation

@mamoreau-devolutions

@mamoreau-devolutions Marc-André Moreau (mamoreau-devolutions) commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Retain quantized DWT coefficients per Progressive tile so difference updates compose with their matching surface reference while progressive codec-context state remains isolated.

Reject difference tiles that lack a retained reference instead of decoding them against zeros.

Keep retained surface references across codec grid replacement and ResetGraphics; only deleting the surface releases them.

Copilot AI balanced review requested due to automatic review settings August 18, 2026 13:05
@github-actions github-actions Bot added kind/protocol Affects RDP or related protocol behavior maintainer-required Maintainer review or intervention is required risk/medium Behavioral change that does not substantially alter a core public API scope/core Touches the core architectural tier size/M Size: up to 449 counted lines and 10 files; exceeds S in either measure labels Aug 18, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Progressive RemoteFX difference-tile decoding with retained per-context tile references.

Changes:

  • Defines the difference-tile flag.
  • Accumulates difference coefficients and rejects missing references.
  • Adds difference-tile regression tests.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
crates/ironrdp-pdu/src/codecs/rfx/progressive.rs Defines and tests the difference flag.
crates/ironrdp-graphics/src/progressive.rs Retains references and decodes difference tiles.

Comment thread crates/ironrdp-graphics/src/progressive.rs Outdated
Comment thread crates/ironrdp-graphics/src/progressive.rs Outdated
@github-actions github-actions Bot added ai-reviewed/1 One automated review completed and removed maintainer-required Maintainer review or intervention is required labels Aug 18, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds decode support for RFX_TILE_DIFFERENCE in Progressive TILE_SIMPLE/TILE_FIRST tiles: retains a tile's quantized DWT coefficients as a reference, sums a difference tile's decoded delta onto it, and returns MissingTileReference instead of silently decoding against zero when no prior tile exists. Well-scoped, keeps the existing decode_first signature, and adds two targeted tests (cross-context accumulation, missing-reference error). Arithmetic and error logic match the supplied protocol handoff's conformance analysis for MS-RDPEGFX 3.2.8.1.4 and 3.3.8.2.1/.1. Two secondary handoff points (context- vs surface-scoped reference lifetime, saturating vs wrapping addition) are real but low-impact. One added point: a new variant on a non-exhaustive-unmarked public error enum is a legitimate but expected semver note.

Protocol analysis: accepted — Re-derived the mappings independently: TILE_FLAG_DIFFERENCE=0x01 matches the documented flags bit for TILE_SIMPLE/TILE_FIRST; the zero-then-add-back-reference sequence is algebraically equivalent to DecDwtQ = Ref + DecProgQ*PQF (difference) vs DecProgQ*PQF (original), with sign state always cleared; gating on pass != 0 (else MissingTileReference) defensibly enforces the encoder-side 'first send is always original' rule. The two potential_discrepancies are correctly low-confidence: context-vs-surface keying predates this diff, and saturating_add is a safe divergence from unspecified overflow behavior, not a wire defect.

Comment thread crates/ironrdp-graphics/src/progressive.rs Outdated
Comment thread crates/ironrdp-graphics/src/progressive.rs
Comment thread crates/ironrdp-graphics/src/progressive.rs
@github-actions github-actions Bot added breaking-change Includes a breaking change, and requires special scrutiny at the boundaries maintainer-required Maintainer review or intervention is required risk/high Substantial core public API impact, or fail-closed triage; needs maintainer-level scrutiny size/L Size: up to 899 counted lines and 20 files; exceeds M in either measure ai-reviewed/2 Final automated review completed and removed risk/medium Behavioral change that does not substantially alter a core public API size/M Size: up to 449 counted lines and 10 files; exceeds S in either measure ai-reviewed/1 One automated review completed labels Aug 18, 2026
@mamoreau-devolutions
Marc-André Moreau (mamoreau-devolutions) force-pushed the copilot/retain-progressive-difference-tiles branch from 5db30b5 to b468942 Compare August 18, 2026 14:37
@github-actions github-actions Bot added risk/unknown Risk could not be determined automatically; needs maintainer-level scrutiny and removed risk/high Substantial core public API impact, or fail-closed triage; needs maintainer-level scrutiny labels Aug 18, 2026
Retain quantized DWT coefficients per Progressive tile so difference updates compose with their matching surface and codec-context reference.

Reject difference tiles that lack a retained reference instead of decoding them against zeros.
Keep RFX Progressive DecDwtQ references on the surface after codec contexts are deleted and commit first-pass decode state only on success.
Keep sub-band difference references through codec grid replacement and
ResetGraphics, releasing them only with their associated surface.

This preserves valid difference-tile state per MS-RDPEGFX lifetime rules.
@ysalitrynskyi

Copy link
Copy Markdown

Same bug as #1701. Keying the reference by surface and keeping it across ResetGraphics is the right model (MS-RDPEGFX 3.3.1.3) — mine conflated it with the codec context.

One substantive point: rejecting a difference tile that has no retained reference. 3.3.8.2.1 makes the zeroing conditional — "if the tile is an original tile (not a difference tile), then the tile MUST be zeroed out in the current frame" — but the add unconditional: "The result of the entropy decode operation MUST be added to the current frame." No error case is defined, and FreeRDP decodes against a zero-initialised current. The error also propagates out of decode_bitmap, so one such tile discards every other tile in the same PDU and handle_wire_to_surface2 turns it into a channel error. Decoding against zero degrades one tile instead.

Nit: FLAG_TILE_DIFFERENCE would match the existing FLAG_DWT_REDUCE_EXTRAPOLATE.

Tests in #1701 you may want to lift: TILE_FIRST end to end (only TILE_SIMPLE is exercised here), the reduce-extrapolate band layout, and a difference tile arriving after an upgrade pass.

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

Labels

ai-reviewed/2 Final automated review completed breaking-change Includes a breaking change, and requires special scrutiny at the boundaries kind/protocol Affects RDP or related protocol behavior maintainer-required Maintainer review or intervention is required risk/unknown Risk could not be determined automatically; needs maintainer-level scrutiny scope/core Touches the core architectural tier size/L Size: up to 899 counted lines and 20 files; exceeds M in either measure

Development

Successfully merging this pull request may close these issues.

3 participants