feat: use imported texture on iOS

This commit is contained in:
Nick Fisher
2024-09-30 14:51:11 +08:00
parent fbd54a2a09
commit e1efd5e4e0
11 changed files with 233 additions and 221 deletions

View File

@@ -1,4 +1,3 @@
export 'thermion_flutter_android.dart';
export 'thermion_flutter_macos.dart';
export 'thermion_flutter_windows.dart';
export 'thermion_flutter_ios.dart';
export 'thermion_flutter_texture_backed_platform.dart';

View File

@@ -1,131 +0,0 @@
import 'dart:async';
import 'package:flutter/services.dart';
import 'dart:ffi';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:thermion_dart/src/viewer/src/ffi/thermion_viewer_ffi.dart';
import 'package:thermion_flutter_ffi/thermion_flutter_method_channel_interface.dart';
import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_interface.dart';
import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart';
import 'package:logging/logging.dart';
///
/// An implementation of [ThermionFlutterPlatform] that uses
/// Flutter platform channels to create a rendering context,
/// resource loaders, and surface/render target(s).
///
class ThermionFlutterIOS
extends ThermionFlutterMethodChannelInterface {
final _channel = const MethodChannel("dev.thermion.flutter/event");
final _logger = Logger("ThermionFlutterFFI");
ThermionViewerFFI? _viewer;
ThermionFlutterIOS._() {}
RenderTarget? _renderTarget;
SwapChain? _swapChain;
static void registerWith() {
ThermionFlutterPlatform.instance = ThermionFlutterIOS._();
}
final _textures = <ThermionFlutterTexture>{};
bool _creatingTexture = false;
bool _destroyingTexture = false;
bool _resizing = false;
///
/// Create a rendering surface.
///
/// This is internal; unless you are [thermion_*] package developer, don't
/// call this yourself.
///
/// The name here is slightly misleading because we only create
/// a texture render target on macOS and iOS; on Android, we render into
/// a native window derived from a Surface, and on Windows we render into
/// a HWND.
///
/// Currently, this only supports a single "texture" (aka rendering surface)
/// at any given time. If a [ThermionWidget] is disposed, it will call
/// [destroyTexture]; if it is resized, it will call [resizeTexture].
///
/// In future, we probably want to be able to create multiple distinct
/// textures/render targets. This would make it possible to have multiple
/// Flutter Texture widgets, each with its own Filament View attached.
/// The current design doesn't accommodate this (for example, it seems we can
/// only create a single native window from a Surface at any one time).
///
Future<ThermionFlutterTexture?> createTexture(int width, int height) async {
throw Exception("TODO");
// note that when [ThermionWidget] is disposed, we don't destroy the
// texture; instead, we keep it around in case a subsequent call requests
// a texture of the same size.
// if (_textures.length > 1) {
// throw Exception("Multiple textures not yet supported");
// } else if (_textures.length == 1) {
// if (_textures.first.height == physicalHeight &&
// _textures.first.width == physicalWidth) {
// return _textures.first;
// } else {
// await _viewer!.setRendering(false);
// await _swapChain?.destroy();
// await destroyTexture(_textures.first);
// _textures.clear();
// }
// }
// _creatingTexture = true;
// var result = await _channel.invokeMethod("createTexture",
// [physicalWidth, physicalHeight, offsetLeft, offsetLeft]);
// if (result == null || (result[0] == -1)) {
// throw Exception("Failed to create texture");
// }
// final flutterTextureId = result[0] as int?;
// final hardwareTextureId = result[1] as int?;
// final surfaceAddress = result[2] as int?;
// _logger.info(
// "Created texture with flutter texture id ${flutterTextureId}, hardwareTextureId $hardwareTextureId and surfaceAddress $surfaceAddress");
// final texture = ThermionFlutterTexture(flutterTextureId, hardwareTextureId,
// physicalWidth, physicalHeight, surfaceAddress);
// await _viewer?.createSwapChain(physicalWidth, physicalHeight,
// surface: texture.surfaceAddress == null
// ? nullptr
// : Pointer<Void>.fromAddress(texture.surfaceAddress!));
// if (texture.hardwareTextureId != null) {
// if (_renderTarget != null) {
// await _renderTarget!.destroy();
// }
// // ignore: unused_local_variable
// _renderTarget = await _viewer?.createRenderTarget(
// physicalWidth, physicalHeight, texture.hardwareTextureId!);
// }
// await _viewer?.updateViewportAndCameraProjection(
// physicalWidth.toDouble(), physicalHeight.toDouble());
// _creatingTexture = false;
// _textures.add(texture);
// return texture;
}
///
/// Called by [ThermionWidget] to resize a texture. Don't call this yourself.
///
@override
Future resizeWindow(
int width,
int height,
int offsetLeft,
int offsetTop,
) async {
throw Exception("Not supported on iOS");
}
}

View File

@@ -11,18 +11,18 @@ import 'package:logging/logging.dart';
/// Flutter platform channels to create a rendering context,
/// resource loaders, and surface/render target(s).
///
class ThermionFlutterMacOS extends ThermionFlutterMethodChannelInterface {
class ThermionFlutterTextureBackedPlatform extends ThermionFlutterMethodChannelInterface {
final _channel = const MethodChannel("dev.thermion.flutter/event");
final _logger = Logger("ThermionFlutterMacOS");
final _logger = Logger("ThermionFlutterTextureBackedPlatform");
static SwapChain? _swapChain;
ThermionFlutterMacOS._();
ThermionFlutterTextureBackedPlatform._();
static ThermionFlutterMacOS? instance;
static ThermionFlutterTextureBackedPlatform? instance;
static void registerWith() {
instance ??= ThermionFlutterMacOS._();
instance ??= ThermionFlutterTextureBackedPlatform._();
ThermionFlutterPlatform.instance = instance!;
}
@@ -32,15 +32,16 @@ class ThermionFlutterMacOS extends ThermionFlutterMethodChannelInterface {
if (_swapChain != null) {
throw Exception("Only a single swapchain can be created");
}
// this is the headless swap chain
// since we will be using render targets, the actual dimensions don't matter
// this implementation renders directly into a texture/render target
// we still need to create a (headless) swapchain, but the actual dimensions
// don't matter
_swapChain = await viewer.createSwapChain(1, 1);
return viewer;
}
// On desktop platforms, textures are always created
Future<ThermionFlutterTexture?> createTexture(int width, int height) async {
var texture = MacOSMethodChannelFlutterTexture(_channel);
var texture = ThermionFlutterTexture(_channel);
await texture.resize(width, height, 0, 0);
return texture;
}
@@ -65,8 +66,8 @@ class TextureCacheEntry {
}
class MacOSMethodChannelFlutterTexture extends MethodChannelFlutterTexture {
final _logger = Logger("MacOSMethodChannelFlutterTexture");
class ThermionFlutterTexture extends MethodChannelFlutterTexture {
final _logger = Logger("ThermionFlutterTexture");
int flutterId = -1;
int hardwareId = -1;
@@ -75,7 +76,7 @@ class MacOSMethodChannelFlutterTexture extends MethodChannelFlutterTexture {
static final Map<String, List<TextureCacheEntry>> _textureCache = {};
MacOSMethodChannelFlutterTexture(super.channel);
ThermionFlutterTexture(super.channel);
@override
Future<void> resize(
@@ -115,7 +116,7 @@ class MacOSMethodChannelFlutterTexture extends MethodChannelFlutterTexture {
final newEntry = TextureCacheEntry(flutterId, hardwareId, inUse: true);
_textureCache.putIfAbsent(cacheKey, () => []).add(newEntry);
_logger.info(
"Created new MacOS texture: flutter id $flutterId, hardware id $hardwareId");
"Created new texture: flutter id $flutterId, hardware id $hardwareId");
}
// Mark old texture as not in use
@@ -160,7 +161,7 @@ class MacOSMethodChannelFlutterTexture extends MethodChannelFlutterTexture {
}
}
Future<void> _destroyTexture(int flutterId, int hardwareId) async {
Future<void> _destroyTexture(int flutterId, int? hardwareId) async {
try {
await channel.invokeMethod("destroyTexture", [flutterId, hardwareId]);
_logger.info("Destroyed old texture: flutter id $flutterId, hardware id $hardwareId");

View File

@@ -11,11 +11,11 @@ flutter:
implements: thermion_flutter_platform_interface
platforms:
ios:
dartPluginClass: ThermionFlutterIOS
dartPluginClass: ThermionFlutterTextureBackedPlatform
android:
dartPluginClass: ThermionFlutterAndroid
macos:
dartPluginClass: ThermionFlutterMacOS
dartPluginClass: ThermionFlutterTextureBackedPlatform
windows:
dartPluginClass: ThermionFlutterWindows
dependencies: