Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Windows] Compositor rendering regresses apps with faded backgrounds #140828

Closed
2 of 3 tasks
loic-sharma opened this issue Jan 2, 2024 · 5 comments
Closed
2 of 3 tasks
Assignees
Labels
a: desktop Running on desktop P2 Important issues not at the top of the work list platform-windows Building on or for Windows specifically

Comments

@loic-sharma
Copy link
Member

loic-sharma commented Jan 2, 2024

Background

flutter/engine#49262 updated Flutter Windows to render to an offscreen framebuffer instead of directly onto the window's surface. This will allow us to support platform views and multiple views.

Unfortunately, this change regresses package:material_floating_search_bar_2's animation and causes weird artifacts.

`package:material_floating_search_bar_2` example...

(FYI there's a more minimal repro below)

import 'package:flutter/material.dart';
import 'package:material_floating_search_bar_2/material_floating_search_bar_2.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // This seems to be necessary to repro:
      debugShowCheckedModeBanner: false, 
      home: Scaffold(
        resizeToAvoidBottomInset: false,
        body: FloatingSearchBar(
          // This seems to be necessary to repro:
          transition: CircularFloatingSearchBarTransition(spacing: 16),
          // This isn't necessary but it makes the artifacts more obvious: 
          transitionDuration: const Duration(seconds: 5),
          builder: (BuildContext context, _) {
            return Material(
             // This seems to be necessary to repro:
              borderRadius: BorderRadius.circular(8), 
              child: const Text('Hello world'),
            );
          },
          body: Container(),
        ),
      ),
    );
  }
}

Minimal repro

Download Windows app.zip

Commit Scenario Works?
9c2a756 Windows OpenGL
b417fb8 Windows OpenGL
b417fb8 Windows software rendering
b417fb8 Linux OpenGL
b417fb8 Web
Source code...
import 'package:flutter/material.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  // Pump frames non-stop. This isn't necessary to repro.
  WidgetsBinding.instance.addPersistentFrameCallback((_) {
    WidgetsBinding.instance.scheduleFrame();
  });

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    // This is necessary to reproduce:
    return Container(
      color: Colors.white,
      child: const Directionality(
        textDirection: TextDirection.ltr,
        child: BlueCircle(),
      ),
    );
  }
}

class BlueCircle extends StatelessWidget {
  const BlueCircle({super.key});

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        const Opacity(
          opacity: 0.3,
          child: SizedBox.expand(
            child: DecoratedBox(
              decoration: BoxDecoration(color: Colors.black),
            ),
          ),
        ),

        SizedBox.expand(
          child: ClipOval(
            clipper: const _CircularRevealClipper(),
            child: DecoratedBox(
              decoration: BoxDecoration(
                color: Colors.blue,
                // Removing this line fixes the app.
                borderRadius: BorderRadius.circular(16.0),
              ),
              child: const SizedBox(height: 256.0),
            ),
          ),
        ),
      ],
    );
  }
}

class _CircularRevealClipper extends CustomClipper<Rect> {
  const _CircularRevealClipper();

  @override
  Rect getClip(Size size) {
    return Rect.fromCircle(
      center: Offset.zero,
      radius: 500,
    );
  }

  @override
  bool shouldReclip(CustomClipper<Rect> oldClipper) => true;
}
Screenshot of the expected output...

image

Screenshot of the actual output...

image

TODO

  • The engine has a dirty region feature that can be disabled. Check if disabling this fixes the issue. RenderDoc showed that the framebuffer contains the expected texture. It appears that the compositor's glFramebufferBlit is the issue.
  • Enable Skia canvas trace commands to verify "good" and "bad" commits are drawing the same things
  • Use a GPU frame debugger (like RenderDoc) to look at GL calls
@loic-sharma loic-sharma added platform-windows Building on or for Windows specifically a: desktop Running on desktop labels Jan 2, 2024
@loic-sharma loic-sharma self-assigned this Jan 2, 2024
auto-submit bot pushed a commit to flutter/engine that referenced this issue Jan 2, 2024
…49461)

This reverts #49262 (00d7d23) as it regressed [`material_floating_search_bar`](https://pub.dev/packages/material_floating_search_bar_2)'s animation.

This revert was created manually due to merge conflicts.

Issue tracking bug: flutter/flutter#140828

Part of flutter/flutter#128904

<details>
<summary>Minimal repro of the broken animation...</summary>

Here's what the animation is supposed to look like:
![good](https://publish-01.obsidian.md/access/b48ac8ca270cd9dac18c4a64d11b1c02/assets/2023-12-28-compositor_animation_regression_good.gif)

Here's what the animation actually looks like: ![bad](https://publish-01.obsidian.md/access/b48ac8ca270cd9dac18c4a64d11b1c02/assets/2023-12-28-compositor_animation_regression_bad.gif)

Here is a minimal repro of the broken animation:

```dart
// The Windows compositor changes regresses the animation in
// the `material_floating_search_bar_2` package:
// 
// https://pub.dev/packages/material_floating_search_bar_2/versions/0.5.0
//
// Below is a minimal repro of the broken animation. This has two pieces:
//
//  1. The background fades to a grey color
//  2. A box is "revealed" using a custom clipper
//
// On framework commit b417fb8 this animation is broken on Windows.
// On framework commit 9c2a756 this animation works as expected on Windows.
//
// Good gif: https://publish-01.obsidian.md/access/b48ac8ca270cd9dac18c4a64d11b1c02/assets/2023-12-28-compositor_animation_regression_good.gif
// Bad gif: https://publish-01.obsidian.md/access/b48ac8ca270cd9dac18c4a64d11b1c02/assets/2023-12-28-compositor_animation_regression_bad.gif
import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @OverRide
  Widget build(BuildContext context) {
    // Not using `MaterialApp` is necessary to reproduce:
    return Container(
      color: Colors.white,
      child: const Directionality(
        textDirection: TextDirection.ltr,
        child: FloatingSearchBar(),
      ),
    );

    // Switching to `MaterialApp` fixes the issue:
    // return const MaterialApp(
    //   home: Scaffold(
    //     body: FloatingSearchBar(),
    //   ),
    // );
  }
}

class FloatingSearchBar extends StatefulWidget {
  const FloatingSearchBar({super.key});

  @OverRide
  FloatingSearchBarState createState() => FloatingSearchBarState();
}

class FloatingSearchBarState extends State<FloatingSearchBar> with SingleTickerProviderStateMixin {
  late final AnimationController _controller = AnimationController(
    vsync: this,
    duration: const Duration(seconds: 2),
  );

  @OverRide
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _animate() {
    if (_controller.isDismissed || _controller.status == AnimationStatus.reverse) {
      _controller.forward();
    } else {
      _controller.reverse();
    }
  }

  @OverRide
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (BuildContext context, _) {
        return Stack(
          children: <Widget>[
            if (!_controller.isDismissed)
              FadeTransition(
                opacity: _controller,
                child: const SizedBox.expand(
                  child: DecoratedBox(
                    decoration: BoxDecoration(color: Colors.black26),
                  ),
                ),
              ),

            _buildSearchBar(),
          ],
        );
      },
    );
  }

  Widget _buildSearchBar() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: <Widget>[
        // This is where the search text input would go...
        GestureDetector(
          onTap: () => _animate(),
          child: Text(
            switch (_controller.status) {
              AnimationStatus.forward || AnimationStatus.completed => 'Click to close',
              AnimationStatus.reverse || AnimationStatus.dismissed => 'Click to open',
            },
            style: const TextStyle(color: Colors.black),
          ),
        ),
        
        // Below are where the search results would be. Clicking on the search
        // input above reveals the results below.

        // Removing this fixes the background's fade transition.
        ClipOval(
          clipper: _CircularRevealClipper(
            fraction: _controller.value,
          ),
          child: DecoratedBox(
            decoration: BoxDecoration(
              color: Colors.white,
              // Removing this line fixes the background's fade transition.
              borderRadius: BorderRadius.circular(16.0),
            ),
            child: const Padding(
              padding: EdgeInsets.all(64.0),
              child: Text(
                'Hello world',
                style: TextStyle(color: Colors.black),
              ),
            ),
          ),
        ),
      ],
    );
  }
}

class _CircularRevealClipper extends CustomClipper<Rect> {
  const _CircularRevealClipper({required this.fraction});

  final double fraction;

  @OverRide
  Rect getClip(Size size) {
    final double halfWidth = size.width * 0.5;
    final double maxRadius = sqrt(halfWidth * halfWidth + size.height * size.height);
    final double radius = lerpDouble(0.0, maxRadius, fraction) ?? 0;

    return Rect.fromCircle(
      center: Offset(halfWidth, 0),
      radius: radius,
    );
  }

  @OverRide
  bool shouldReclip(CustomClipper<Rect> oldClipper) {
    if (oldClipper is _CircularRevealClipper) {
      return oldClipper.fraction != fraction;
    }

    return true;
  }
}

```

</details>

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
@loic-sharma loic-sharma added the P2 Important issues not at the top of the work list label Jan 4, 2024
@loic-sharma
Copy link
Member Author

loic-sharma commented Jan 4, 2024

Skia tracing

Here are timeline traces with Skia enabled:

Platform Flutter commit Engine commit Animation works? Trace download link
Windows 9c2a756 flutter/engine@2e55306 Trace
Windows 9c2a756 flutter/engine@00d7d23 Trace
Linux 9c2a756 flutter/engine@00d7d23 Trace

You can open these using chrome://tracing in your browser.

Engine commits:

  1. flutter/engine@2e55306 - Windows renders to the root surface
  2. flutter/engine@00d7d23 - Both Windows and Linux render to an OpenGL framebuffer (Windows implementation, Linux implementation)

Comparison of Linux and Windows traces

Here's a comparison of the traces for a single frame of the animation on Linux and Windows while on flutter/engine@00d7d23.

Traces...

Notable differences are bolded.

Traces inside OpsTask::onPrepare:

Linux Windows
FillRectOp
FillRectOp
CircularRRectOp
FillRectOp
FillRectOp
CircularRRectOp

Traces between OpsTask::onPrepare and OpsTask::onExecute

Linux Windows
  1. Disable(0x0B71)
  2. DepthMask(0)
  3. FrontFace(0x0901)
  4. Disable(0x8037)
  5. Enable(0x8642)
  6. LineWidth(1)
  7. Enable(0x809D)
  8. PixelStorei(0x0CF2, 0)
  9. BindBuffer(bufferState->fGLTarget, glBuffer->bufferID())
  10. InvalidateBufferData(bufferID)
  11. BufferSubData(target, offset, size, src)
  12. BindVertexArray(arrayID)
  13. InvalidateBufferData(bufferID)
  14. BufferSubData(target, offset, size, src)
  1. Disable(0x0B71)
  2. DepthMask(0)
  3. Disable(0x0B44)
  4. FrontFace(0x0901)
  5. LineWidth(1)
  6. Disable(0x0BD0)
  7. PixelStorei(0x0CF2, 0)
  8. PixelStorei(0x0D02, 0)
  9. PixelStorei(0x93A4, 0)
  10. BindBuffer(bufferState->fGLTarget, glBuffer->bufferID())
  11. BufferData(target, bufferSize, nullptr, usage)
  12. BufferSubData(target, offset, size, src)
  13. BindVertexArray(arrayID)
  14. BindBuffer(bufferState->fGLTarget, glBuffer->bufferID())
  15. BufferData(target, bufferSize, nullptr, usage)
  16. BufferSubData(target, offset, size, src)

Traces inside OpsTask::onExecute:

Linux Windows
  1. BindFramebuffer(target, fboid)
  2. CheckFramebufferStatus(0x8D40)
  3. Viewport(nativeViewport.fX, nativeViewport.fY, nativeViewport.fWidth, nativeViewport.fHeight)
  4. Disable(0x8DB9)
  5. ClearColor(r, g, b, a)
  6. ColorMask(1, 1, 1, 1)
  7. Clear(clearMask)
  1. BindFramebuffer(target, fboid)
  2. CheckFramebufferStatus(0x8D40)
  3. Viewport(nativeViewport.fX, nativeViewport.fY, nativeViewport.fWidth, nativeViewport.fHeight)
FillRectOp
  1. DrawRangeElements(glPrimType, minIndexValue, maxIndexValue, indexCount, 0x1403, this->offsetForBaseIndex(baseIndex))
FillRectOp
  1. UseProgram(id)
  2. Enable(0x0BE2)
  3. BlendEquation(gXfermodeEquation2Blend[(int)equation])
  4. BlendFunc(gXfermodeCoeff2Blend[(int)srcCoeff], gXfermodeCoeff2Blend[(int)dstCoeff])
  5. ColorMask(1, 1, 1, 1)
  6. Disable(0x0B90)
  7. Disable(0x0C11)
  8. EnableVertexAttribArray(i)
  9. EnableVertexAttribArray(i)
  10. DisableVertexAttribArray(i)
  11. DisableVertexAttribArray(i)
  12. ... Repeat DisableVertexAttribArray(i) several times...
  13. DisableVertexAttribArray(i)
  14. VertexAttribPointer(index, layout.fCount, layout.fType, layout.fNormalized, stride, offsetAsPtr)
  15. VertexAttribDivisor(index, divisor)
  16. VertexAttribPointer(index, layout.fCount, layout.fType, layout.fNormalized, stride, offsetAsPtr)
  17. VertexAttribDivisor(index, divisor)
  18. DrawArrays(glPrimType, baseVertex, vertexCount)
CircularRRectOp
  1. UseProgram(id)
  2. Uniform4fv(uni.fLocation, arrayCount, v)
  3. Enable(0x0C11)
  4. Scissor(nativeScissor.fX, nativeScissor.fY, nativeScissor.fWidth, nativeScissor.fHeight)
  5. BindBuffer(0x8893, glBuffer->bufferID())
  6. EnableVertexAttribArray(i)
  7. VertexAttribPointer(index, layout.fCount, layout.fType, layout.fNormalized, stride, offsetAsPtr)
  8. VertexAttribDivisor(index, divisor)
  9. DrawRangeElements(glPrimType, minIndexValue, maxIndexValue, indexCount, 0x1403, this->offsetForBaseIndex(baseIndex))
CircularRRectOp
  1. UseProgram(id)
  2. Uniform4fv(uni.fLocation, arrayCount, v)
  3. Enable(0x0C11)
  4. Scissor(nativeScissor.fX, nativeScissor.fY, nativeScissor.fWidth, nativeScissor.fHeight)
  5. BindBuffer(bufferState->fGLTarget, glBuffer->bufferID())
  6. EnableVertexAttribArray(i)
  7. VertexAttribPointer(index, layout.fCount, layout.fType, layout.fNormalized, stride, offsetAsPtr)
  8. VertexAttribPointer(index, layout.fCount, layout.fType, layout.fNormalized, stride, offsetAsPtr)
  9. VertexAttribPointer(index, layout.fCount, layout.fType, layout.fNormalized, stride, offsetAsPtr)
  10. VertexAttribDivisor(index, divisor)
  11. DrawRangeElements(glPrimType, minIndexValue, maxIndexValue, indexCount, 0x1403, this->offsetForBaseIndex(baseIndex))

Notable differences between the traces:

  1. Traces inside OpsTask::onPrepare: no notable differences!
  2. Traces between OpsTask::onPrepare and OpsTask::onExecute:
    1. Linux calls InvalidateBufferData
  3. Traces inside OpsTask::onExecute:
    1. Linux calls ClearColor(...), ColorMask(...), Clear(...) before it executes ops
    2. Windows's FillRectOp execution calls BlendEquation(...) and BlendFunc(...)

@loic-sharma
Copy link
Member Author

loic-sharma commented Jan 9, 2024

I have a smaller minimal repro: a clipped circle stacked on top of a faded background:

Minimal source code...
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    // This is necessary to reproduce:
    return Container(
      color: Colors.white,
      child: const Directionality(
        textDirection: TextDirection.ltr,
        child: BlueCircle(),
      ),
    );

    // Switching to this fixes the issue:
    // return const MaterialApp(
    //   home: Scaffold(
    //     body: BlueCircle(),
    //   ),
    // );
  }
}

class BlueCircle extends StatelessWidget {
  const BlueCircle({super.key});

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        const Opacity(
          opacity: 0.3,
          child: SizedBox.expand(
            child: DecoratedBox(
              decoration: BoxDecoration(color: Colors.black),
            ),
          ),
        ),

        SizedBox.expand(
          child: ClipOval(
            clipper: const _CircularRevealClipper(),
            child: DecoratedBox(
              decoration: BoxDecoration(
                color: Colors.blue,
                // Removing this line fixes the app.
                borderRadius: BorderRadius.circular(16.0),
              ),
              child: const SizedBox(height: 256.0),
            ),
          ),
        ),
      ],
    );
  }
}

class _CircularRevealClipper extends CustomClipper<Rect> {
  const _CircularRevealClipper();

  @override
  Rect getClip(Size size) {
    return Rect.fromCircle(
      center: Offset.zero,
      radius: 500,
    );
  }

  @override
  bool shouldReclip(CustomClipper<Rect> oldClipper) => true;
}

I verified the framebuffer's texture is properly rendered using RenderDoc. The blit appears to be broken somehow.

I updated the Windows compositor to clear the window surface to red before blitting the backing store's framebuffer. If blitting works as expected, the red should not be visible as the entire surface should have been blitted over. However, red color remains:

image

Patch to clear the window surface to red before blitting...

Apply this patch on flutter/engine@00d7d23:

diff --git a/shell/platform/windows/compositor_opengl.cc b/shell/platform/windows/compositor_opengl.cc
index 6da274b993..c19cab4af1 100644
--- a/shell/platform/windows/compositor_opengl.cc
+++ b/shell/platform/windows/compositor_opengl.cc
@@ -132,6 +132,10 @@ bool CompositorOpenGL::Present(const FlutterLayer** layers,
     return false;
   }

+  gl_->BindFramebuffer(GL_DRAW_FRAMEBUFFER, kWindowFrameBufferId);
+  gl_->ClearColor(1.0f, 0.0f, 0.0f, 0.0f);
+  gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
   auto source_id = layers[0]->backing_store->open_gl.framebuffer.name;
   gl_->BindFramebuffer(GL_READ_FRAMEBUFFER, source_id);
   gl_->BindFramebuffer(GL_DRAW_FRAMEBUFFER, kWindowFrameBufferId);

This appears to be ANGLE's blit implementation on D3D11: https://github.com/google/angle/blob/95fe7e470418cd5ac18d203eb29a25101c650f14/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp#L576

@loic-sharma
Copy link
Member Author

loic-sharma commented Jan 10, 2024

ANGLE bug report

https://chromium.slack.com/archives/CGHH6049K/p1704925434965249

I believe Flutter Windows is affected by what appears to be a bug in ANGLE's glBlitFramebuffer implementation on D3D11.

Example app

Here is a Flutter app that draws a rounded rectangle with a circular clip on top of a faded background:

app.zip

Source code...

This is broken on Flutter commit b417fb828b332b0a4b0c80b742d86aa922de2649.
This works on Flutter commit 9c2a7560096223090d38bbd5b4c46760be396bc1.

import 'package:flutter/material.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  // Pump frames non-stop. This isn't necessary to repro.
  WidgetsBinding.instance.addPersistentFrameCallback((_) {
    WidgetsBinding.instance.scheduleFrame();
  });

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    // This is necessary to reproduce:
    return Container(
      color: Colors.white,
      child: const Directionality(
        textDirection: TextDirection.ltr,
        child: BlueCircle(),
      ),
    );
  }
}

class BlueCircle extends StatelessWidget {
  const BlueCircle({super.key});

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        const Opacity(
          opacity: 0.3,
          child: SizedBox.expand(
            child: DecoratedBox(
              decoration: BoxDecoration(color: Colors.black),
            ),
          ),
        ),

        SizedBox.expand(
          child: ClipOval(
            clipper: const _CircularRevealClipper(),
            child: DecoratedBox(
              decoration: BoxDecoration(
                color: Colors.blue,
                // Removing this line fixes the app.
                borderRadius: BorderRadius.circular(16.0),
              ),
              child: const SizedBox(height: 256.0),
            ),
          ),
        ),
      ],
    );
  }
}

class _CircularRevealClipper extends CustomClipper<Rect> {
  const _CircularRevealClipper();

  @override
  Rect getClip(Size size) {
    return Rect.fromCircle(
      center: Offset.zero,
      radius: 500,
    );
  }

  @override
  bool shouldReclip(CustomClipper<Rect> oldClipper) => true;
}
Screenshot of the expected output...

image

Screenshot of the actual output...

image

Analysis

Flutter Windows uses Skia and ANGLE to render to an OpenGL framebuffer. Flutter Windows then blits this framebuffer to the window's surface. The blit updates the entire window surface (the framebuffer and window surface have the same size).

Using RenderDoc's texture viewer, we can inspect the blit (event ID 57): renderdoc.zip

  1. ✅ The input texture ANGLE_TexStorage2D contains the expected content
  2. ❌ The output texture ANGLE_BackBufferTexture is unexpected

Clear test

It appears that the blit is not updating the entire window surface. To test this hypothesis, I added a step to clear the window's surface to a red color immediately before blitting the framebuffer. Since the blit should update the entire window surface, no red color should be visible. However, the red color is visible:

Screenshot of test app...

Notice how red color is visible. This indicates the blit did not update the entire window surface.

image

Here is the RenderDoc capture: red_test_capture.zip

Debugging information

Affected Flutter version: b417fb8
ANGLE version for affected Flutter version: google/angle@6a09e41

Perfetto trace of Skia and its OpenGL calls...

Inspect this in Chrome by navigating to chrome://tracing:

perfetto_trace.json

The OpenGL calls are in the io.flutter.raster swim lane. Use W to zoom in and a/d to pan left/right. This does not include the glFramebufferBlit GL call.

@loic-sharma loic-sharma changed the title [Windows] Compositor rendering regresses animation [Windows] Compositor rendering regresses apps with faded backgrounds Jan 11, 2024
auto-submit bot pushed a commit to flutter/engine that referenced this issue Jan 16, 2024
## Original pull request description

This migrates the Windows embedder to `FlutterCompositor` so that the engine renders off-screen to a framebuffer instead of directly onto the window's surface. This will allow us to support platform views and multiple views on Windows.

Addresses flutter/flutter#128904

## Reland (again)

#49262 was reverted as it regressed [`package:material_floating_search_bar_2`](https://pub.dev/packages/material_floating_search_bar_2/versions/0.5.0). See: flutter/flutter#140828

This pull request is split into the following commits:

1. d337378 is the previous reland pull request, unchanged
2. e866af0 disables the scissor test before blitting the framebuffer, allowing us to "force" copy the framebuffer's contents by ignoring scissoring values

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
@loic-sharma
Copy link
Member Author

Fixed by flutter/engine#49726

Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 31, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: desktop Running on desktop P2 Important issues not at the top of the work list platform-windows Building on or for Windows specifically
Projects
None yet
Development

No branches or pull requests

1 participant