Skip to content

Reland "refactor(web): Unify Image on Skwasm and CanvasKit"#188356

Merged
auto-submit[bot] merged 19 commits into
flutter:masterfrom
harryterkelsen:web-unify-image
Jun 23, 2026
Merged

Reland "refactor(web): Unify Image on Skwasm and CanvasKit"#188356
auto-submit[bot] merged 19 commits into
flutter:masterfrom
harryterkelsen:web-unify-image

Conversation

@harryterkelsen

Copy link
Copy Markdown
Contributor

Introduces EngineImage and BackendImage, with EngineImage handling all of the shared logic for implementing an Image in the Flutter Engine, and BackendImage as a thin wrapper around the native Image object.

Another step towards #175630

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Introduces EngineImage and BackendImage, with EngineImage handling all of the
shared logic for implementing an Image in the Flutter Engine, and BackendImage
as a thin wrapper around the native Image object.

Another step towards flutter#175630
… to avoid WebGL GPU stalls

Using OffscreenCanvas to encode PNG asynchronously requires extracting raw pixels
via readPixels first. For GPU-backed textures (where imageSource is null),
this readPixels call causes a synchronous WebGL GPU stall that blocks the main
thread for seconds and triggers Chrome's aggressive background tab throttling,
causing integration tests to fail.

By bypassing this fallback for GPU-backed textures and using Skia's native C++
PNG encoder, we avoid the GPU stall entirely, restoring rendering performance
and test stability.
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 22, 2026
@harryterkelsen
harryterkelsen requested a review from mdebbar June 22, 2026 22:20
@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. platform-web Web applications specifically team-web Owned by Web platform team labels Jun 22, 2026

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request refactors the web engine's image representation by introducing EngineImage as a frontend wrapper that delegates graphics resources to backend-specific implementations (CkImageDelegate and SkwasmImage) via a new BackendImage interface, while managing backing browser resources using reference-counted ImageSource wrappers. The review feedback identifies several critical issues, including potential native memory leaks in scaleImage, SkwasmAnimatedImageDecoder, and createSkwasmImageFromPixels due to missing try-finally blocks around native resource allocations. Additionally, there is a potential use-after-free vulnerability in EngineImage.toByteData in release mode, precision loss in scaleImage due to integer division, and opportunities to simplify repetitive casting in both CanvasKit and Skwasm canvas implementations.

Comment thread engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/image.dart
Comment thread engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/canvas.dart Outdated
Comment thread engine/src/flutter/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/canvas.dart Outdated
Comment thread engine/src/flutter/lib/web_ui/lib/src/engine/primitives/image.dart
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 22, 2026
@harryterkelsen

Copy link
Copy Markdown
Contributor Author

/gemini review

@harryterkelsen harryterkelsen added the CICD Run CI/CD label Jun 22, 2026

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request refactors the web engine's image handling by introducing 'EngineImage' as a frontend representation that delegates graphics resources to a 'BackendImage' interface, implemented by 'CkImageDelegate' and 'SkwasmImage'. It also extracts shared pixel source logic into a reference-counted 'ImageSource' class. Feedback on these changes suggests optimizing native memory copying in 'SkwasmSurface.rasterizeImage' using 'asTypedList' and adding a defensive assertion in 'unpremultiplyRawRgba' to verify that the pixel buffer length is a multiple of four.

@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 22, 2026
@harryterkelsen

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request refactors the web engine's image handling by introducing the EngineImage and BackendImage abstractions, replacing direct usages of CkImage and SkwasmImage with backend-specific delegates. It also moves ImageSource and its subclasses to a separate primitives file and updates canvases, shaders, renderers, and tests accordingly. Feedback on the changes highlights a runtime issue in image.dart where a JSPromise from convertToBlob() is awaited without calling .toDart, and a potential null-pointer exception in scaleImage when both target dimensions are non-positive.

Comment thread engine/src/flutter/lib/web_ui/lib/src/engine/primitives/image.dart
Comment thread engine/src/flutter/lib/web_ui/lib/src/engine/canvaskit/image.dart Outdated
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 22, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 23, 2026
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 23, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 23, 2026
@harryterkelsen harryterkelsen added the CICD Run CI/CD label Jun 23, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 23, 2026
@harryterkelsen harryterkelsen added the CICD Run CI/CD label Jun 23, 2026
@harryterkelsen harryterkelsen added the autosubmit Merge PR when tree becomes green via auto submit App label Jun 23, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Jun 23, 2026
Merged via the queue into flutter:master with commit 4a39bd8 Jun 23, 2026
204 of 205 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jun 23, 2026
via-guy pushed a commit to via-guy/flutter that referenced this pull request Jun 26, 2026
…188356)

Introduces EngineImage and BackendImage, with EngineImage handling all
of the shared logic for implementing an Image in the Flutter Engine, and
BackendImage as a thin wrapper around the native Image object.

Another step towards flutter#175630

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-web Web applications specifically team-web Owned by Web platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants