From dd7d1d2db9bd16583c9e52969b505cd15720ad0f Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 21 May 2026 20:33:21 -0700 Subject: [PATCH 1/2] Add breaking change notice for OpenGL ES render-to-texture orientation --- .../content/release/breaking-changes/index.md | 2 + .../opengles-render-to-texture-top-down.md | 71 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 sites/docs/src/content/release/breaking-changes/opengles-render-to-texture-top-down.md diff --git a/sites/docs/src/content/release/breaking-changes/index.md b/sites/docs/src/content/release/breaking-changes/index.md index ff1825ff29..53d650a924 100644 --- a/sites/docs/src/content/release/breaking-changes/index.md +++ b/sites/docs/src/content/release/breaking-changes/index.md @@ -37,8 +37,10 @@ They're sorted by release and listed in alphabetical order: ### Not yet released to stable * [Large screen orientation and resizability restrictions ignored on Android 17][] +* [OpenGL ES render-to-texture content is stored top-down][] [Large screen orientation and resizability restrictions ignored on Android 17]: /release/breaking-changes/android-large-screens-restrictions-ignored +[OpenGL ES render-to-texture content is stored top-down]: /release/breaking-changes/opengles-render-to-texture-top-down ### Released in Flutter 3.44 diff --git a/sites/docs/src/content/release/breaking-changes/opengles-render-to-texture-top-down.md b/sites/docs/src/content/release/breaking-changes/opengles-render-to-texture-top-down.md new file mode 100644 index 0000000000..f443ed4368 --- /dev/null +++ b/sites/docs/src/content/release/breaking-changes/opengles-render-to-texture-top-down.md @@ -0,0 +1,71 @@ +--- +title: OpenGL ES render-to-texture content is stored top-down +description: >- + Impeller's OpenGL ES backend now stores render-to-texture content + top-down, matching Metal and Vulkan, which can affect Flutter GPU + apps that compensated for the previous bottom-up orientation. +--- + +{% render "docs/breaking-changes.md" %} + +## Summary + +Impeller's OpenGL ES backend now stores render-to-texture content +top-down, the same as the Metal and Vulkan backends. +A Flutter GPU app that sampled a render-target texture on OpenGL ES and +added a vertical flip to compensate for the old bottom-up orientation +now renders that content upside down. + +## Background + +The OpenGL ES backend previously stored render-to-texture content +bottom-up, unlike the Metal and Vulkan backends. +The renderer carried that orientation difference through every texture +sample as a per-sampler Y-coordinate scale. +Impeller now absorbs the difference once, at the vertex stage, so +render-target textures are stored top-down on every backend. + +This change is invisible to the framework and to Flutter's 2D rendering. +The only surface where application code could observe the old +orientation is Flutter GPU, the experimental `flutter_gpu` package, +where an app drives render passes and samples render-target textures +directly. + +## Migration guide + +If a Flutter GPU shader flipped the Y coordinate when sampling a +render-target texture solely to make OpenGL ES match the other backends, +remove that flip. +Render-target textures are now top-down on every backend. + +Code before migration: + +```glsl +// The flip only compensated for OpenGL ES's bottom-up render targets. +uv.y = 1.0 - uv.y; +frag_color = texture(u_texture, uv); +``` + +Code after migration: + +```glsl +frag_color = texture(u_texture, uv); +``` + +## Timeline + +Landed in version: not yet released
+In stable release: Not yet + +## References + +GitHub issue: + +* [Issue 186554][] + +Relevant PR: + +* [PR 186556][] + +[Issue 186554]: {{site.repo.flutter}}/issues/186554 +[PR 186556]: {{site.repo.flutter}}/pull/186556 From f39736652675c2c613a7667b4b91e68da97dd8b7 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Tue, 9 Jun 2026 13:08:26 -0700 Subject: [PATCH 2/2] Address review: cover FragmentShader API and full preprocessor block Broaden the notice to fragment shaders alongside Flutter GPU, and show the whole IMPELLER_TARGET_OPENGLES conditional in the migration code, including a cross-release option using IMPELLER_OPENGLES_UNFLIPPED_DEPRECATED. --- .../opengles-render-to-texture-top-down.md | 65 ++++++++++++++----- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/sites/docs/src/content/release/breaking-changes/opengles-render-to-texture-top-down.md b/sites/docs/src/content/release/breaking-changes/opengles-render-to-texture-top-down.md index f443ed4368..8051f25fb9 100644 --- a/sites/docs/src/content/release/breaking-changes/opengles-render-to-texture-top-down.md +++ b/sites/docs/src/content/release/breaking-changes/opengles-render-to-texture-top-down.md @@ -2,8 +2,9 @@ title: OpenGL ES render-to-texture content is stored top-down description: >- Impeller's OpenGL ES backend now stores render-to-texture content - top-down, matching Metal and Vulkan, which can affect Flutter GPU - apps that compensated for the previous bottom-up orientation. + top-down, matching Metal and Vulkan, which can affect fragment shaders + and Flutter GPU apps that compensated for the previous bottom-up + orientation. --- {% render "docs/breaking-changes.md" %} @@ -12,9 +13,9 @@ description: >- Impeller's OpenGL ES backend now stores render-to-texture content top-down, the same as the Metal and Vulkan backends. -A Flutter GPU app that sampled a render-target texture on OpenGL ES and -added a vertical flip to compensate for the old bottom-up orientation -now renders that content upside down. +A fragment shader or Flutter GPU app that sampled a render-target texture +on OpenGL ES and added a vertical flip to compensate for the old +bottom-up orientation now renders that content upside down. ## Background @@ -26,36 +27,62 @@ Impeller now absorbs the difference once, at the vertex stage, so render-target textures are stored top-down on every backend. This change is invisible to the framework and to Flutter's 2D rendering. -The only surface where application code could observe the old -orientation is Flutter GPU, the experimental `flutter_gpu` package, -where an app drives render passes and samples render-target textures +Application code can only observe the old orientation through the +`FragmentShader` API and through Flutter GPU, the experimental +`flutter_gpu` package, where a shader samples a render-target texture directly. ## Migration guide -If a Flutter GPU shader flipped the Y coordinate when sampling a -render-target texture solely to make OpenGL ES match the other backends, -remove that flip. -Render-target textures are now top-down on every backend. +Shaders written for OpenGL ES often flipped the Y coordinate inside an +`IMPELLER_TARGET_OPENGLES` block to make render-target textures match the +other backends. +Render-target textures are now top-down on every backend, so that flip is +no longer needed. Code before migration: ```glsl -// The flip only compensated for OpenGL ES's bottom-up render targets. -uv.y = 1.0 - uv.y; -frag_color = texture(u_texture, uv); +void main() { + vec2 uv = FlutterFragCoord().xy / u_size; +#ifdef IMPELLER_TARGET_OPENGLES + uv.y = 1.0 - uv.y; +#endif + fragColor = texture(u_texture, uv); +} ``` +If the shader only needs to run on a Flutter release that includes this +change, remove the flip. + Code after migration: ```glsl -frag_color = texture(u_texture, uv); +void main() { + vec2 uv = FlutterFragCoord().xy / u_size; + fragColor = texture(u_texture, uv); +} +``` + +To keep one source working across releases, guard the flip with the +`IMPELLER_OPENGLES_UNFLIPPED_DEPRECATED` macro. +That macro is only defined on releases that store render-target textures +top-down, so the flip still runs on older releases that need it. + +```glsl +void main() { + vec2 uv = FlutterFragCoord().xy / u_size; +#if defined(IMPELLER_TARGET_OPENGLES) && !defined(IMPELLER_OPENGLES_UNFLIPPED_DEPRECATED) + uv.y = 1.0 - uv.y; +#endif + fragColor = texture(u_texture, uv); +} ``` ## Timeline Landed in version: not yet released
-In stable release: Not yet +In stable release: the next stable release after 3.44.0 ## References @@ -63,9 +90,11 @@ GitHub issue: * [Issue 186554][] -Relevant PR: +Relevant PRs: * [PR 186556][] +* [PR 187316][] [Issue 186554]: {{site.repo.flutter}}/issues/186554 [PR 186556]: {{site.repo.flutter}}/pull/186556 +[PR 187316]: {{site.repo.flutter}}/pull/187316