rendering correctly with backing window but some issues re pixel density, scroll & foregrounding on start

This commit is contained in:
Nick Fisher
2023-10-25 17:52:37 +11:00
parent 8cea106b30
commit 0928d9d273
13 changed files with 404 additions and 376 deletions

View File

@@ -19,6 +19,14 @@ class TextureDetails {
}
abstract class FilamentController {
///
/// Whether a Flutter Texture widget should be inserted into the widget hierarchy.
/// This will be false on certain platforms where we use a transparent window underlay.
/// Used internally by [FilamentWidget]; you probably don't need to access this property directly.
///
bool get requiresTextureWidget;
///
/// The Flutter texture ID and dimensions for current texture in use.
/// This is only used by [FilamentWidget]; you shouldn't need to access directly yourself.

View File

@@ -4,16 +4,21 @@ import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/services.dart';
import 'package:ffi/ffi.dart';
import 'package:flutter/widgets.dart';
import 'package:polyvox_filament/filament_controller.dart';
import 'package:polyvox_filament/animations/animation_data.dart';
import 'package:polyvox_filament/generated_bindings.dart';
// ignore: constant_identifier_names
const FilamentEntity _FILAMENT_ASSET_ERROR = 0;
class FilamentControllerFFI extends FilamentController {
late MethodChannel _channel = MethodChannel("app.polyvox.filament/event");
final _channel = const MethodChannel("app.polyvox.filament/event");
@override
bool get requiresTextureWidget => !Platform.isWindows;
double _pixelRatio = 1.0;
@@ -25,9 +30,11 @@ class FilamentControllerFFI extends FilamentController {
final String? uberArchivePath;
@override
Stream<bool> get hasViewer => _hasViewerController.stream;
final _hasViewerController = StreamController<bool>();
@override
Stream<FilamentEntity> get pickResult => _pickResultController.stream;
final _pickResultController = StreamController<FilamentEntity>.broadcast();
@@ -48,7 +55,7 @@ class FilamentControllerFFI extends FilamentController {
_resizeTimer?.cancel();
_resizingWidth = call.arguments[0];
_resizingHeight = call.arguments[1];
_resizeTimer = Timer(Duration(milliseconds: 500), () async {
_resizeTimer = Timer(const Duration(milliseconds: 500), () async {
await resize(_resizingWidth!, _resizingHeight!);
});
@@ -160,7 +167,7 @@ class FilamentControllerFFI extends FilamentController {
print("Using flutterTextureId $flutterTextureId, surface $surfaceAddress and nativeTexture $nativeTexture");
if (Platform.isWindows) {
if (Platform.isWindows && requiresTextureWidget) {
_driver = Pointer<Void>.fromAddress(
await _channel.invokeMethod("getDriverPlatform"));
}
@@ -275,6 +282,10 @@ class FilamentControllerFFI extends FilamentController {
@override
Future resize(int width, int height, {double scaleFactor = 1.0}) async {
if(Platform.isWindows) {
return;
}
// we defer to the FilamentWidget to ensure that every call to [resize] is synchronized
// so this exception should never be thrown (right?)
if (textureDetails.value == null) {

View File

@@ -42,7 +42,7 @@ class _RenderResizeObserver extends RenderProxyBox {
void performLayout() async {
super.performLayout();
if (size.width != _oldSize.width || size.height != _oldSize.height) {
onLayoutChangedCallback(size);
onLayoutChangedCallback(size);
_oldSize = Size(size.width, size.height);
}
}
@@ -87,7 +87,7 @@ class _FilamentWidgetState extends State<FilamentWidget> {
return ResizeObserver(
onResized: (newSize) {
if(!Platform.isWindows) {
if (!Platform.isWindows) {
return;
}
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
@@ -124,10 +124,10 @@ class _SizedFilamentWidget extends StatefulWidget {
}
class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
String? _error;
late final AppLifecycleListener _appLifecycleListener;
AppLifecycleState? _lastState;
@override
void initState() {
@@ -136,9 +136,6 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
if (!kReleaseMode) {
await Future.delayed(Duration(seconds: 2));
}
try {
await widget.controller.createViewer(widget.width, widget.height);
} catch (err) {
@@ -171,7 +168,7 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
var width = size.width.ceil();
var height = size.height.ceil();
while (_resizing) {
await Future.delayed(Duration(milliseconds: 20));
await Future.delayed(const Duration(milliseconds: 20));
}
_resizing = true;
await widget.controller.resize(width, height);
@@ -237,7 +234,6 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
await widget.controller.setRendering(_wasRenderingOnInactive);
break;
}
_lastState = state;
}
@override
@@ -252,31 +248,55 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
]));
}
return ListenableBuilder(listenable: widget.controller.textureDetails, builder: (BuildContext ctx, Widget? wdgt) {
if (widget.controller.textureDetails.value == null) {
return Stack(children: [
Positioned.fill(child: widget.initial ?? Container(color: Colors.red))
]);
}
// see [FilamentControllerFFI.resize] for an explanation of how we deal with resizing
var texture = Texture(
key: ObjectKey("texture_${widget.controller.textureDetails.value!.textureId}"),
textureId: widget.controller.textureDetails.value!.textureId,
filterQuality: FilterQuality.none,
freeze: false,
);
if (!widget.controller.requiresTextureWidget) {
return Stack(children: [
Positioned.fill(
child: Platform.isLinux || Platform.isWindows
? Transform(
alignment: Alignment.center,
transform: Matrix4.rotationX(
pi), // TODO - this rotation is due to OpenGL texture coordinate working in a different space from Flutter, can we move this to the C++ side somewhere?
child: texture)
: texture)
Positioned.fill(child: CustomPaint(painter: TransparencyPainter()))
]);
});
}
return ListenableBuilder(
listenable: widget.controller.textureDetails,
builder: (BuildContext ctx, Widget? wdgt) {
if (widget.controller.textureDetails.value == null) {
return Stack(children: [
Positioned.fill(
child: widget.initial ?? Container(color: Colors.red))
]);
}
// see [FilamentControllerFFI.resize] for an explanation of how we deal with resizing
var texture = Texture(
key: ObjectKey(
"texture_${widget.controller.textureDetails.value!.textureId}"),
textureId: widget.controller.textureDetails.value!.textureId,
filterQuality: FilterQuality.none,
freeze: false,
);
return Stack(children: [
Positioned.fill(
child: Platform.isLinux || Platform.isWindows
? Transform(
alignment: Alignment.center,
transform: Matrix4.rotationX(
pi), // TODO - this rotation is due to OpenGL texture coordinate working in a different space from Flutter, can we move this to the C++ side somewhere?
child: texture)
: texture)
]);
});
}
}
class TransparencyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
canvas.drawRect(
Rect.fromLTWH(0, 0, size.width, size.height),
Paint()
..blendMode = BlendMode.clear
..color = const Color(0x00000000),
);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}