fix: clean up destruction logic for FlutterPlatformTexture

This commit is contained in:
Nick Fisher
2024-10-22 12:47:35 +08:00
parent bb10a75f0e
commit 9244009350

View File

@@ -21,6 +21,8 @@ class FlutterPlatformTexture extends MethodChannelFlutterTexture {
late bool destroySwapChainOnResize; late bool destroySwapChainOnResize;
bool destroyed = false;
FlutterPlatformTexture( FlutterPlatformTexture(
super.channel, this.viewer, this.view, this.swapChain) { super.channel, this.viewer, this.view, this.swapChain) {
if (swapChain == null) { if (swapChain == null) {
@@ -33,10 +35,13 @@ class FlutterPlatformTexture extends MethodChannelFlutterTexture {
@override @override
Future<void> resize( Future<void> resize(
int newWidth, int newHeight, int newLeft, int newTop) async { int newWidth, int newHeight, int newLeft, int newTop) async {
_logger.info(
"Resizing texture to $newWidth x $newHeight (offset $newLeft, $newTop)");
if (newWidth == this.width && if (newWidth == this.width &&
newHeight == this.height && newHeight == this.height &&
newLeft == 0 && newLeft == 0 &&
newTop == 0) { newTop == 0) {
_logger.info("Existing texture matches requested dimensions");
return; return;
} }
@@ -51,44 +56,65 @@ class FlutterPlatformTexture extends MethodChannelFlutterTexture {
_lastFlutterId = flutterId; _lastFlutterId = flutterId;
_lastHardwareId = hardwareId; _lastHardwareId = hardwareId;
flutterId = result[0] as int; flutterId = result[0] as int;
hardwareId = result[1] as int; hardwareId = result[1] as int;
if (destroySwapChainOnResize) { _logger.info("Created texture ${flutterId} / ${hardwareId}");
await swapChain?.destroy();
if (destroySwapChainOnResize && swapChain != null) {
await viewer.destroySwapChain(swapChain!);
swapChain = await viewer.createSwapChain(result[2]); swapChain = await viewer.createSwapChain(result[2]);
} }
_logger.info(
"Created new texture: flutter id $flutterId, hardware id $hardwareId");
if (destroySwapChainOnResize) { if (destroySwapChainOnResize) {
await view.setRenderable(true, swapChain!); await view.setRenderable(true, swapChain!);
} else if (hardwareId != _lastHardwareId) { } else if (hardwareId != _lastHardwareId) {
await _renderTarget?.destroy(); if (_renderTarget != null) {
await viewer.destroyRenderTarget(_renderTarget!);
}
_renderTarget = _renderTarget =
await viewer.createRenderTarget(width, height, hardwareId); await viewer.createRenderTarget(width, height, hardwareId);
await view.setRenderTarget(_renderTarget!); await view.setRenderTarget(_renderTarget!);
await view.setRenderable(true, swapChain!); await view.setRenderable(true, swapChain!);
await _destroyTexture(_lastFlutterId, _lastHardwareId); if (_lastFlutterId != -1 && _lastHardwareId != -1) {
await _destroyTexture(_lastFlutterId, _lastHardwareId);
_lastFlutterId = -1;
_lastHardwareId = -1;
}
} }
} }
Future<void> _destroyTexture(int flutterId, int? hardwareId) async { Future<void> _destroyTexture(
int flutterTextureId, int hardwareTextureId) async {
try { try {
await channel.invokeMethod("destroyTexture", [flutterId, hardwareId]); await channel.invokeMethod(
_logger.info( "destroyTexture", [flutterTextureId, hardwareTextureId]);
"Destroyed old texture: flutter id $flutterId, hardware id $hardwareId"); _logger.info("Destroyed texture $flutterTextureId / $hardwareTextureId");
} catch (e) { } catch (e) {
_logger.severe("Failed to destroy texture: $e"); _logger.severe("Failed to destroy texture: $e");
} }
} }
bool destroying = false;
Future destroy() async { Future destroy() async {
if (destroyed || destroying) {
return;
}
destroying = true;
await view.setRenderTarget(null); await view.setRenderTarget(null);
await _renderTarget?.destroy(); if (_renderTarget != null) {
await swapChain?.destroy(); await viewer.destroyRenderTarget(_renderTarget!);
await channel.invokeMethod("destroyTexture", hardwareId); _renderTarget = null;
}
if (destroySwapChainOnResize && swapChain != null) {
await viewer.destroySwapChain(swapChain!);
swapChain = null;
}
await _destroyTexture(flutterId, hardwareId);
flutterId = -1;
hardwareId = -1;
destroying = false;
destroyed = true;
} }
Future markFrameAvailable() async { Future markFrameAvailable() async {