fix mac render memory, dispose old decoded image (#8140)
Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
parent
e7f0f0ff8d
commit
0442f7012b
@ -237,6 +237,8 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
_ffi.inputModel.enterOrLeave(false);
|
_ffi.inputModel.enterOrLeave(false);
|
||||||
DesktopMultiWindow.removeListener(this);
|
DesktopMultiWindow.removeListener(this);
|
||||||
_ffi.dialogManager.hideMobileActionsOverlay();
|
_ffi.dialogManager.hideMobileActionsOverlay();
|
||||||
|
_ffi.imageModel.disposeImage();
|
||||||
|
_ffi.cursorModel.disposeImages();
|
||||||
_ffi.recordingModel.onClose();
|
_ffi.recordingModel.onClose();
|
||||||
_rawKeyFocusNode.dispose();
|
_rawKeyFocusNode.dispose();
|
||||||
await _ffi.close(closeSession: closeSession);
|
await _ffi.close(closeSession: closeSession);
|
||||||
|
@ -90,6 +90,8 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
gFFI.dialogManager.hideMobileActionsOverlay();
|
gFFI.dialogManager.hideMobileActionsOverlay();
|
||||||
gFFI.inputModel.listenToMouse(false);
|
gFFI.inputModel.listenToMouse(false);
|
||||||
|
gFFI.imageModel.disposeImage();
|
||||||
|
gFFI.cursorModel.disposeImages();
|
||||||
await gFFI.invokeMethod("enable_soft_keyboard", true);
|
await gFFI.invokeMethod("enable_soft_keyboard", true);
|
||||||
_mobileFocusNode.dispose();
|
_mobileFocusNode.dispose();
|
||||||
_physicalFocusNode.dispose();
|
_physicalFocusNode.dispose();
|
||||||
|
@ -1208,6 +1208,7 @@ class ImageModel with ChangeNotifier {
|
|||||||
parent.target?.canvasModel.updateViewStyle();
|
parent.target?.canvasModel.updateViewStyle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_image?.dispose();
|
||||||
_image = image;
|
_image = image;
|
||||||
if (image != null) notifyListeners();
|
if (image != null) notifyListeners();
|
||||||
}
|
}
|
||||||
@ -1231,6 +1232,11 @@ class ImageModel with ChangeNotifier {
|
|||||||
final yscale = size.height / _image!.height;
|
final yscale = size.height / _image!.height;
|
||||||
return min(xscale, yscale) / 1.5;
|
return min(xscale, yscale) / 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void disposeImage() {
|
||||||
|
_image?.dispose();
|
||||||
|
_image = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ScrollStyle {
|
enum ScrollStyle {
|
||||||
@ -1702,6 +1708,7 @@ class PredefinedCursor {
|
|||||||
final defaultImg = _image2!;
|
final defaultImg = _image2!;
|
||||||
// This function is called only one time, no need to care about the performance.
|
// This function is called only one time, no need to care about the performance.
|
||||||
Uint8List data = defaultImg.getBytes(order: img2.ChannelOrder.rgba);
|
Uint8List data = defaultImg.getBytes(order: img2.ChannelOrder.rgba);
|
||||||
|
_image?.dispose();
|
||||||
_image = await img.decodeImageFromPixels(
|
_image = await img.decodeImageFromPixels(
|
||||||
data, defaultImg.width, defaultImg.height, ui.PixelFormat.rgba8888);
|
data, defaultImg.width, defaultImg.height, ui.PixelFormat.rgba8888);
|
||||||
|
|
||||||
@ -1937,6 +1944,11 @@ class CursorModel with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disposeImages() {
|
||||||
|
_images.forEach((_, v) => v.item1.dispose());
|
||||||
|
_images.clear();
|
||||||
|
}
|
||||||
|
|
||||||
updateCursorData(Map<String, dynamic> evt) async {
|
updateCursorData(Map<String, dynamic> evt) async {
|
||||||
final id = int.parse(evt['id']);
|
final id = int.parse(evt['id']);
|
||||||
final hotx = double.parse(evt['hotx']);
|
final hotx = double.parse(evt['hotx']);
|
||||||
@ -1947,7 +1959,11 @@ class CursorModel with ChangeNotifier {
|
|||||||
final rgba = Uint8List.fromList(colors.map((s) => s as int).toList());
|
final rgba = Uint8List.fromList(colors.map((s) => s as int).toList());
|
||||||
final image = await img.decodeImageFromPixels(
|
final image = await img.decodeImageFromPixels(
|
||||||
rgba, width, height, ui.PixelFormat.rgba8888);
|
rgba, width, height, ui.PixelFormat.rgba8888);
|
||||||
|
if (image == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (await _updateCache(rgba, image, id, hotx, hoty, width, height)) {
|
if (await _updateCache(rgba, image, id, hotx, hoty, width, height)) {
|
||||||
|
_images[id]?.item1.dispose();
|
||||||
_images[id] = Tuple3(image, hotx, hoty);
|
_images[id] = Tuple3(image, hotx, hoty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import 'package:flutter/widgets.dart';
|
|||||||
|
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
|
|
||||||
Future<ui.Image> decodeImageFromPixels(
|
Future<ui.Image?> decodeImageFromPixels(
|
||||||
Uint8List pixels,
|
Uint8List pixels,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
@ -18,36 +18,74 @@ Future<ui.Image> decodeImageFromPixels(
|
|||||||
}) async {
|
}) async {
|
||||||
if (targetWidth != null) {
|
if (targetWidth != null) {
|
||||||
assert(allowUpscaling || targetWidth <= width);
|
assert(allowUpscaling || targetWidth <= width);
|
||||||
|
if (!(allowUpscaling || targetWidth <= width)) {
|
||||||
|
print("not allow upscaling but targetWidth > width");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (targetHeight != null) {
|
if (targetHeight != null) {
|
||||||
assert(allowUpscaling || targetHeight <= height);
|
assert(allowUpscaling || targetHeight <= height);
|
||||||
}
|
if (!(allowUpscaling || targetHeight <= height)) {
|
||||||
|
print("not allow upscaling but targetHeight > height");
|
||||||
final ui.ImmutableBuffer buffer =
|
return null;
|
||||||
await ui.ImmutableBuffer.fromUint8List(pixels);
|
|
||||||
onPixelsCopied?.call();
|
|
||||||
final ui.ImageDescriptor descriptor = ui.ImageDescriptor.raw(
|
|
||||||
buffer,
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
rowBytes: rowBytes,
|
|
||||||
pixelFormat: format,
|
|
||||||
);
|
|
||||||
if (!allowUpscaling) {
|
|
||||||
if (targetWidth != null && targetWidth > descriptor.width) {
|
|
||||||
targetWidth = descriptor.width;
|
|
||||||
}
|
|
||||||
if (targetHeight != null && targetHeight > descriptor.height) {
|
|
||||||
targetHeight = descriptor.height;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final ui.Codec codec = await descriptor.instantiateCodec(
|
final ui.ImmutableBuffer buffer;
|
||||||
targetWidth: targetWidth,
|
try {
|
||||||
targetHeight: targetHeight,
|
buffer = await ui.ImmutableBuffer.fromUint8List(pixels);
|
||||||
);
|
onPixelsCopied?.call();
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ui.ImageDescriptor descriptor;
|
||||||
|
try {
|
||||||
|
descriptor = ui.ImageDescriptor.raw(
|
||||||
|
buffer,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
rowBytes: rowBytes,
|
||||||
|
pixelFormat: format,
|
||||||
|
);
|
||||||
|
if (!allowUpscaling) {
|
||||||
|
if (targetWidth != null && targetWidth > descriptor.width) {
|
||||||
|
targetWidth = descriptor.width;
|
||||||
|
}
|
||||||
|
if (targetHeight != null && targetHeight > descriptor.height) {
|
||||||
|
targetHeight = descriptor.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("ImageDescriptor.raw failed: $e");
|
||||||
|
buffer.dispose();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ui.Codec codec;
|
||||||
|
try {
|
||||||
|
codec = await descriptor.instantiateCodec(
|
||||||
|
targetWidth: targetWidth,
|
||||||
|
targetHeight: targetHeight,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
print("instantiateCodec failed: $e");
|
||||||
|
buffer.dispose();
|
||||||
|
descriptor.dispose();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ui.FrameInfo frameInfo;
|
||||||
|
try {
|
||||||
|
frameInfo = await codec.getNextFrame();
|
||||||
|
} catch (e) {
|
||||||
|
print("getNextFrame failed: $e");
|
||||||
|
codec.dispose();
|
||||||
|
buffer.dispose();
|
||||||
|
descriptor.dispose();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
final ui.FrameInfo frameInfo = await codec.getNextFrame();
|
|
||||||
codec.dispose();
|
codec.dispose();
|
||||||
buffer.dispose();
|
buffer.dispose();
|
||||||
descriptor.dispose();
|
descriptor.dispose();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user