feat: use imported texture on iOS
This commit is contained in:
@@ -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';
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user