fix(egfx): bound the compositor's dirty-region metadata - #1510
Merged
Marc-André Moreau (mamoreau-devolutions) merged 1 commit intoAug 3, 2026
Conversation
The compositor charges materialized pixel buffers against its byte budget but not the dirty-region entries that produce them. The repeat filter is O(1) and only collapses consecutive repeats, so a peer that alternates two rectangles and never sends EndFrame adds one entry per rectangle with nothing stopping it. RDPGFX_POINT16 is four bytes on the wire against ten bytes resident per entry, so the queue grows at 2.5 times the cost to the sender. Charging the entry puts it under the same ceiling as the pixel buffers; EndFrame returns the charge before materializing, so the pixel copies can spend what the metadata was holding.
Greg Lamberson (glamberson)
force-pushed
the
fix/egfx-dirty-region-budget
branch
from
August 3, 2026 00:40
5e83059 to
57492c5
Compare
Greg Lamberson (glamberson)
requested a review
from Marc-André Moreau (mamoreau-devolutions)
August 3, 2026 02:48
Marc-André Moreau (mamoreau-devolutions)
approved these changes
Aug 3, 2026
Marc-André Moreau (mamoreau-devolutions)
merged commit Aug 3, 2026
81f7392
into
Devolutions:master
26 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
MAX_COMPOSITOR_BYTESbut not theDirtyRegionentries that produce them, soframegrows outside the budget.EndFrame, and the peer chooses when that happens.record_dirtynow charges one entry before pushing, andEndFramereleases the whole set before materializing so the pixel copies can spend what the metadata was holding.Cost to the peer
RDPGFX_POINT16(2.2.1.1) is four bytes on the wire;RDPGFX_RECT16(2.2.1.2) is eight. ADirtyRegionis ten bytes resident. Three commands loop over these arrays and record one dirty region each:RDPGFX_SOLIDFILL_PDU(2.2.2.4)fillRects, RECT16RDPGFX_SURFACE_TO_SURFACE_PDU(2.2.2.5)destPts, POINT16RDPGFX_CACHE_TO_SURFACE_PDU(2.2.2.7)destPts, POINT16The ratios are modest. The point is that there was no ceiling at all, so a sustained stream grows the queue until the client is out of memory regardless of ratio.
Validation
cargo xtask check fmt/lints/tests/typos/locksall pass.Notes
Veccapacity. SinceVecgrows by doubling, resident bytes forframecan reach roughly twice the charged figure. This matches the existing accounting, which chargesdata.len()for pixel buffers rather than capacity; flagging it rather than diverging from the established model.materializealready follows for refused allocations, andchargelogs the allocated and budget figures.