Skip to content

[Impeller] drawAtlas with BlendMode.modulate renders incorrectly #127374

@hakonber

Description

@hakonber

Is there an existing issue for this?

Steps to reproduce

In our app we have a CustomPainter that uses Canvas.drawAtlas() in order to render multiple instances of an image. We use the colors and blendMode arguments to apply a tint to the image, using BlendMode.modulate. After updating to Flutter 3.10, which enables Impeller by default, this no longer renders correctly. The image is no longer being tinted with the supplied color. Disabling Impeller (e.g. flutter run --no-enable-impeller) fixes the issue.

Note that the bug only seems to affect physical iOS devices (we have tested on iPhone 13 Pro and iPhone 14 Pro). In the simulator it renders correctly whether Impeller is enabled or not.

Please see the attached code sample below. I have also attached images that show the different behavior between Skia and Impeller.

Expected results

In the attached code sample, a CustomPainter is used to draw an image of a rounded rectangle using drawAtlas(). The image is tinted yellow by passing a colors list and BlendMode.modulate.

The expected result is that the image is rendered correctly (tinted yellow).

Actual results

When using Impeller, the image is not rendered correctly (the colors list and the blend mode isn't respected).

Code sample

Code sample
import 'dart:async';

import 'package:flutter/material.dart';

import 'dart:ui' as ui;

late final ui.Image image;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  image = await generateWhiteImage();
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.blue[100],
      child: Center(
        child: Stack(
          alignment: Alignment.topLeft,
          children: [
            const FlutterLogo(size: 200),
            CustomPaint(
              painter: Painter(),
              size: const Size(400, 400),
            ),
          ],
        ),
      ),
    );
  }
}

/// Generate an image with a white rounded rectangle.
Future<ui.Image> generateWhiteImage() {
  final recorder = ui.PictureRecorder();
  final canvas = Canvas(recorder);
  final paint = Paint()..color = Colors.white;
  canvas.drawRRect(
      RRect.fromRectAndRadius(
        const Rect.fromLTWH(0, 0, 300, 300),
        const Radius.circular(20),
      ),
      paint);
  return recorder.endRecording().toImage(300, 300);
}

class Painter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    // Draw a single instance of the image using drawAtlas, using
    // BlendMode.modulate to apply a yellow tint.
    canvas.drawAtlas(
      image,
      [
        RSTransform.fromComponents(
          rotation: 0,
          scale: 1.0,
          anchorX: 0,
          anchorY: 0,
          translateX: 40,
          translateY: 40,
        ),
      ],
      [Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble())],
      [const Color(0xcffcf5a2)],
      BlendMode.modulate,
      null,
      Paint(),
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

Screenshots or Video

Screenshots / Video demonstration
Skia (flutter run --no-enable-impeller) Impeller (flutter run)

Logs

Logs
$ flutter create bug --platforms ios
Signing iOS app for device deployment using developer identity: "Apple Development: *removed* (*removed*)"
Creating project bug...
Resolving dependencies in bug...
Got dependencies in bug.
Wrote 51 files.

All done!
You can find general documentation for Flutter at: https://docs.flutter.dev/
Detailed API documentation is available at: https://api.flutter.dev/
If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev

In order to run your application, type:

  $ cd bug
  $ flutter run

Your application code is in bug/lib/main.dart.

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.10.1, on macOS 13.3.1 22E772610a darwin-arm64, locale en-NO)
    • Flutter version 3.10.1 on channel stable at /Users/haakon/Applications/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision d3d8effc68 (6 days ago), 2023-05-16 17:59:05 -0700
    • Engine revision b4fb11214d
    • Dart version 3.0.1
    • DevTools version 2.23.1

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
    • Android SDK at /Users/haakon/Library/Android/sdk
    • Platform android-33, build-tools 33.0.1
    • ANDROID_SDK_ROOT = /Users/haakon/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14E222b
    • CocoaPods version 1.12.0

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)

[✓] VS Code (version 1.78.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.64.0

[✓] Connected device (3 available)
    • Håkon sin iPhone 13 Pro (mobile) • 00008110-000044901AA2801E • ios            • iOS 16.4.1 20E252
    • macOS (desktop)                  • macos                     • darwin-arm64   • macOS 13.3.1 22E772610a darwin-arm64
    • Chrome (web)                     • chrome                    • web-javascript • Google Chrome 113.0.5672.126

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Metadata

Metadata

Assignees

Labels

e: impellerImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.found in release: 3.10Found to occur in 3.10found in release: 3.11Found to occur in 3.11has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer version

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions