From 7b1c150e1815534e6deacb2be5515e9c5be15018 Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Sun, 5 Jul 2026 02:28:51 +0200 Subject: [PATCH] feat(android): enable impeller on capable TV devices Impeller was blanket-disabled on TV in e759dafa as a precaution when the Tensor/NVIDIA fallbacks landed, and #749 (API 30 Fire TV Cube freezing until the Skia build) validated it. Flutter has since deprecated the Impeller opt-out, so start walking the disable back where the hardware can take it: TV devices on Android 12+ with a Vulkan 1.1 driver use Impeller, while Fire OS (modern API levels on GPUs whose drivers can't back it up), pre-12 boxes, and the existing NVIDIA/Huawei/e-waste quirks stay on Skia. Tag Sentry events with the active renderer so TV regressions are attributable while this rolls out. --- .../main/kotlin/com/edde746/plezy/MainActivity.kt | 14 ++++++++++++-- lib/main.dart | 6 +++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/kotlin/com/edde746/plezy/MainActivity.kt b/android/app/src/main/kotlin/com/edde746/plezy/MainActivity.kt index 3d0142d4..0123153c 100644 --- a/android/app/src/main/kotlin/com/edde746/plezy/MainActivity.kt +++ b/android/app/src/main/kotlin/com/edde746/plezy/MainActivity.kt @@ -386,8 +386,6 @@ class MainActivity : FlutterActivity() { } private fun shouldDisableImpeller(): Boolean { - // Android TV devices — weaker GPUs, less Impeller testing - if (isAndroidTvDevice()) return true if (DeviceQuirks.isEWaste) return true // NVIDIA Tegra (Shield TV) if (Build.MANUFACTURER.equals("NVIDIA", ignoreCase = true)) return true @@ -397,9 +395,21 @@ class MainActivity : FlutterActivity() { ) { return true } + if (isAndroidTvDevice()) return !tvSupportsImpeller() return false } + // Impeller froze API 30 Fire TV hardware (#749) and Flutter's Vulkan → GLES + // fallback still miscompiles gradients/SVGs, so only TV devices on Android 12+ + // with a Vulkan 1.1 driver leave the Skia path. + private fun tvSupportsImpeller(): Boolean { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return false + // Fire OS reports modern API levels on GPUs whose drivers can't back it up + if (Build.MANUFACTURER.equals("Amazon", ignoreCase = true)) return false + val vulkan11 = 0x401000 // FEATURE_VULKAN_HARDWARE_VERSION encodes 1.1.0 as 0x401000 + return packageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, vulkan11) + } + override fun getRenderMode(): RenderMode { // Keep Flutter in the normal View hierarchy so video/subtitle SurfaceViews // remain the only native composition layers. This restores the pre-1.35.0 diff --git a/lib/main.dart b/lib/main.dart index 4f1c8753..2c1347a5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -213,7 +213,11 @@ Future _bootstrapApp() async { final commitSuffix = gitCommit.isNotEmpty ? ' (${gitCommit.substring(0, 7)})' : ''; String renderer = ''; if (Platform.isAndroid) { - renderer = ' [${await const MethodChannel('com.plezy/theme').invokeMethod('getRenderer')}]'; + final rendererName = await const MethodChannel('com.plezy/theme').invokeMethod('getRenderer'); + renderer = ' [$rendererName]'; + // Tag crash reports with the active renderer while Impeller rolls back + // out to Android TV, so device-specific regressions are attributable. + unawaited(Sentry.configureScope((scope) => scope.setTag('renderer', rendererName ?? 'unknown'))); } appLogger.i( 'Plezy v${packageInfo.version}+${packageInfo.buildNumber}$commitSuffix$renderer'