Strict source rect for sub-rect image draws (flutter/flutter#67881) - #1
Open
lslv1243 wants to merge 3 commits into
Open
Strict source rect for sub-rect image draws (flutter/flutter#67881)#1lslv1243 wants to merge 3 commits into
lslv1243 wants to merge 3 commits into
Conversation
Canvas::drawImageRect always passed SrcRectConstraint::kFast, so atlas cell draws could sample neighbouring cells. Pass kStrict whenever the source rect is a strict sub-rect of the image; full-image draws keep kFast semantics. Also forward the constraint in the Impeller dispatcher, which received it and dropped it (the canvas + TextureContents strict pipeline already existed, unwired). Validated on iOS sim + macOS: sentinel-atlas bleed 0/56 configs on both Skia and Impeller at FilterQuality.none and .low (stock: 3-30/56 none, 56/56 low).
…urce is set DrawImageRect renders the given texture; the paint's color source is irrelevant to it. Dispatchers persist paint attributes across ops and image draws do not re-sync the color source, so a preceding ImageShader draw leaves paint.color_source set. Paint::WithColorFilter's image-source early-return then assumes the color filter was applied by TiledTextureContents and drops it silently. Repro: draw a rect with an ImageShader paint, then drawImageRect with a ColorFilter - the filter is ignored (e.g. mask recolors render raw pixels). Fix: clear the color source on a local paint copy before building the texture entity. Upstream master retains the same early-return; recording-order changes currently mask it there.
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.
Fixes two rendering defects for Fibula Wars, at the engine root, on Flutter 3.27.1 (
cb4b5fff73).1. Strict source rect for sub-rect image draws (flutter/flutter#67881)
Canvas::drawImageRecthardcodedDlSrcRectConstraint::kFast, so sampling reads outside the source rect and atlas cells bleed into neighbours. This PR passeskStrictwhenever the source rect does not cover the whole image:lib/ui/painting/canvas.cc: conditional strict constraint.impeller/display_list/dl_dispatcher.cc: forward the constraint to the Impeller canvas — the strict sampling pipeline existed upstream but the dispatcher dropped the parameter (still true on master as of 2026-08-01).Validated with a sentinel-atlas harness (every neighbour cell magenta): 0/56 bleeding configs at both filter qualities on iOS (Skia Metal + Impeller Metal, sim debug + device release), Android emulator (Skia GL) and Android device (Impeller GLES). Bilinear atlas draws become pixel-identical to isolated textures (0/280).
2. Impeller: stale image color source suppresses texture-draw color filters
Paint::WithColorFilterearly-returns whencolor_sourceis an image color source, assumingTiledTextureContentsapplied the filter. But dispatchers persist paint attributes across ops and image draws don't re-sync the color source — so after anyImageShaderdraw in the same display list, every laterdrawImageRectwith aColorFiltersilently loses the filter (e.g. recolorable masks render their raw pixels).Minimal repro: draw a fullscreen rect with an
ImageShaderpaint, thendrawImageRectwithColorFilter.mode(green, srcIn)+BlendMode.multiplyover a gray base — renders raw red instead of green. Fix:Canvas::DrawImageRectclearscolor_sourceon a local paint copy (the texture is the source; the attribute is irrelevant there). Verified: filtered output returns to the mathematically expected value; full game mask-tint pipeline renders correctly over shader-painted backgrounds.Upstream note: master retains the same early-return; current recording behavior happens to mask the bug there, but the hardening is applicable as-is.
Build compatibility (Xcode 26 / macOS 26 SDK)
Building this 2024-era checkout with Xcode 26 needs two buildroot/libcxx patches, carried in the sibling repos:
math.h: restore C99 classification macros for C++ TUs.-iframework .../SubFrameworksso UIKit's UIUtilities import resolves.