From e67d4d7e1f0809b5c4598de664fa582217751625 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Thu, 16 Nov 2023 12:09:50 +0800 Subject: [PATCH] fix incorrect pixelDeviceRatio --- lib/filament_controller_ffi.dart | 113 ++++++++++++++++--------------- lib/widgets/filament_widget.dart | 37 +++------- 2 files changed, 70 insertions(+), 80 deletions(-) diff --git a/lib/filament_controller_ffi.dart b/lib/filament_controller_ffi.dart index 710dc470..053c0358 100644 --- a/lib/filament_controller_ffi.dart +++ b/lib/filament_controller_ffi.dart @@ -130,8 +130,11 @@ class FilamentControllerFFI extends FilamentController { @override Future setDimensions(Rect rect, double pixelRatio) async { - this.rect.value = Rect.fromLTWH(rect.left, rect.top, - rect.width * _pixelRatio, rect.height * _pixelRatio); + this.rect.value = Rect.fromLTWH( + (rect.left * _pixelRatio).floor().toDouble(), + rect.top * _pixelRatio.floor().toDouble(), + (rect.width * _pixelRatio).ceil().toDouble(), + (rect.height * _pixelRatio).ceil().toDouble()); _pixelRatio = pixelRatio; } @@ -318,64 +321,66 @@ class FilamentControllerFFI extends FilamentController { throw Exception("Cannot resize without active viewer"); } - if (_resizing) { - throw Exception("Resize currently underway, ignoring"); + while (_resizing) { + await Future.delayed(Duration(milliseconds: 100)); } - _resizing = true; + try { + _resizing = true; - set_rendering_ffi(_viewer!, false); + set_rendering_ffi(_viewer!, false); - if (!_usesBackingWindow) { - destroy_swap_chain_ffi(_viewer!); - } - - if (requiresTextureWidget) { - if (textureDetails.value != null) { - await _channel.invokeMethod( - "destroyTexture", textureDetails.value!.textureId); + if (!_usesBackingWindow) { + destroy_swap_chain_ffi(_viewer!); } - } else if (Platform.isWindows) { - dev.log("Resizing window with rect $rect"); - await _channel.invokeMethod("resizeWindow", [ - rect.value!.width, - rect.value!.height, - rect.value!.left, - rect.value!.top - ]); + + if (requiresTextureWidget) { + if (textureDetails.value != null) { + await _channel.invokeMethod( + "destroyTexture", textureDetails.value!.textureId); + } + } else if (Platform.isWindows) { + dev.log("Resizing window with rect $rect"); + await _channel.invokeMethod("resizeWindow", [ + rect.value!.width, + rect.value!.height, + rect.value!.left, + rect.value!.top + ]); + } + + var renderingSurface = await _createRenderingSurface(); + + if (_viewer!.address == 0) { + throw Exception("Failed to create viewer. Check logs for details"); + } + + _assetManager = get_asset_manager(_viewer!); + + if (!_usesBackingWindow) { + create_swap_chain_ffi(_viewer!, renderingSurface.surface, + rect.value!.width.toInt(), rect.value!.height.toInt()); + } + + if (renderingSurface.textureHandle != 0) { + dev.log( + "Creating render target from native texture ${renderingSurface.textureHandle}"); + create_render_target_ffi(_viewer!, renderingSurface.textureHandle, + rect.value!.width.toInt(), rect.value!.height.toInt()); + } + + textureDetails.value = TextureDetails( + textureId: renderingSurface.flutterTextureId, + width: rect.value!.width.toInt(), + height: rect.value!.height.toInt()); + + update_viewport_and_camera_projection_ffi( + _viewer!, rect.value!.width.toInt(), rect.value!.height.toInt(), 1.0); + + await setRendering(_rendering); + } finally { + _resizing = false; } - - var renderingSurface = await _createRenderingSurface(); - - if (_viewer!.address == 0) { - throw Exception("Failed to create viewer. Check logs for details"); - } - - _assetManager = get_asset_manager(_viewer!); - - if (!_usesBackingWindow) { - create_swap_chain_ffi(_viewer!, renderingSurface.surface, - rect.value!.width.toInt(), rect.value!.height.toInt()); - } - - if (renderingSurface.textureHandle != 0) { - dev.log( - "Creating render target from native texture ${renderingSurface.textureHandle}"); - create_render_target_ffi(_viewer!, renderingSurface.textureHandle, - rect.value!.width.toInt(), rect.value!.height.toInt()); - } - - textureDetails.value = TextureDetails( - textureId: renderingSurface.flutterTextureId, - width: rect.value!.width.toInt(), - height: rect.value!.height.toInt()); - - update_viewport_and_camera_projection_ffi( - _viewer!, rect.value!.width.toInt(), rect.value!.height.toInt(), 1.0); - - await setRendering(_rendering); - - _resizing = false; } @override diff --git a/lib/widgets/filament_widget.dart b/lib/widgets/filament_widget.dart index 49d9bb6a..59bfaa37 100644 --- a/lib/widgets/filament_widget.dart +++ b/lib/widgets/filament_widget.dart @@ -125,8 +125,6 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> { late final AppLifecycleListener _appLifecycleListener; - late double _pixelRatio; - Rect get _rect { final renderBox = (context.findRenderObject()) as RenderBox; final size = renderBox.size; @@ -141,24 +139,22 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> { ); WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { - try { - _pixelRatio = MediaQuery.of(context).devicePixelRatio; - widget.controller.setDimensions(_rect, _pixelRatio); + try { + widget.controller.setDimensions(_rect, MediaQuery.of(context).devicePixelRatio); } catch (err) { dev.log("Fatal error : $err"); _error = err.toString(); } - setState(() {}); - }); + }); super.initState(); } + Timer? _resizeTimer; bool _resizing = false; - Future _resize() { - dev.log("Resizing widget"); + Future _resize() async { final completer = Completer(); // resizing the window can be sluggish (particular in debug mode), exacerbated when simultaneously recreating the swapchain and resize the window. // to address this, whenever the widget is resized, we set a timer for Xms in the future. @@ -166,42 +162,31 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> { // any subsequent widget resizes will cancel the timer and replace with a new one. // debug mode does need a longer timeout. _resizeTimer?.cancel(); - - _resizeTimer = Timer( - Duration(milliseconds: (kReleaseMode || Platform.isWindows) ? 10 : 100), - () async { - if (!mounted) { - completer.complete(); - return; - } + _resizeTimer = Timer(Duration(milliseconds: (kReleaseMode || Platform.isWindows) ? 10 : 100), () async { try { - while (_resizing) { + while(_resizing) { await Future.delayed(const Duration(milliseconds: 20)); } - _resizing = true; - await widget.controller.setDimensions(_rect, _pixelRatio); + await widget.controller.setDimensions(_rect, MediaQuery.of(context).devicePixelRatio); await widget.controller.resize(); _resizeTimer = null; setState(() {}); _resizing = false; } catch (err) { dev.log("Error resizing FilamentWidget: $err"); - } finally { + } finally { completer.complete(); } }); - return completer.future; + } @override void didUpdateWidget(_SizedFilamentWidget oldWidget) { super.didUpdateWidget(oldWidget); - - if (oldWidget.height != widget.height || oldWidget.width != widget.width) { - _resize(); - } + _resize(); } @override