* refact: texture render as an option Signed-off-by: fufesou <linlong1266@gmail.com> * refact: texture render, translation Signed-off-by: fufesou <linlong1266@gmail.com> * refact: texture render as option Signed-off-by: fufesou <linlong1266@gmail.com> * Update ui_interface.rs --------- Signed-off-by: fufesou <linlong1266@gmail.com> Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
		
			
				
	
	
		
			245 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:flutter_gpu_texture_renderer/flutter_gpu_texture_renderer.dart';
 | |
| import 'package:flutter_hbb/common/shared_state.dart';
 | |
| import 'package:flutter_hbb/consts.dart';
 | |
| import 'package:flutter_hbb/models/model.dart';
 | |
| import 'package:get/get.dart';
 | |
| 
 | |
| import '../../common.dart';
 | |
| import './platform_model.dart';
 | |
| 
 | |
| import 'package:texture_rgba_renderer/texture_rgba_renderer.dart'
 | |
|     if (dart.library.html) 'package:flutter_hbb/web/texture_rgba_renderer.dart';
 | |
| 
 | |
| class _PixelbufferTexture {
 | |
|   int _textureKey = -1;
 | |
|   int _display = 0;
 | |
|   SessionID? _sessionId;
 | |
|   bool _destroying = false;
 | |
|   int? _id;
 | |
| 
 | |
|   final textureRenderer = TextureRgbaRenderer();
 | |
| 
 | |
|   int get display => _display;
 | |
| 
 | |
|   create(int d, SessionID sessionId, FFI ffi) {
 | |
|     _display = d;
 | |
|     _textureKey = bind.getNextTextureKey();
 | |
|     _sessionId = sessionId;
 | |
| 
 | |
|     textureRenderer.createTexture(_textureKey).then((id) async {
 | |
|       _id = id;
 | |
|       if (id != -1) {
 | |
|         ffi.textureModel.setRgbaTextureId(display: d, id: id);
 | |
|         final ptr = await textureRenderer.getTexturePtr(_textureKey);
 | |
|         platformFFI.registerPixelbufferTexture(sessionId, display, ptr);
 | |
|         debugPrint(
 | |
|             "create pixelbuffer texture: peerId: ${ffi.id} display:$_display, textureId:$id, texturePtr:$ptr");
 | |
|       }
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   destroy(bool unregisterTexture, FFI ffi) async {
 | |
|     if (!_destroying && _textureKey != -1 && _sessionId != null) {
 | |
|       _destroying = true;
 | |
|       if (unregisterTexture) {
 | |
|         platformFFI.registerPixelbufferTexture(_sessionId!, display, 0);
 | |
|         // sleep for a while to avoid the texture is used after it's unregistered.
 | |
|         await Future.delayed(Duration(milliseconds: 100));
 | |
|       }
 | |
|       await textureRenderer.closeTexture(_textureKey);
 | |
|       _textureKey = -1;
 | |
|       _destroying = false;
 | |
|       debugPrint(
 | |
|           "destroy pixelbuffer texture: peerId: ${ffi.id} display:$_display, textureId:$_id");
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _GpuTexture {
 | |
|   int _textureId = -1;
 | |
|   SessionID? _sessionId;
 | |
|   final support = bind.mainHasGpuTextureRender();
 | |
|   bool _destroying = false;
 | |
|   int _display = 0;
 | |
|   int? _id;
 | |
|   int? _output;
 | |
| 
 | |
|   int get display => _display;
 | |
| 
 | |
|   final gpuTextureRenderer = FlutterGpuTextureRenderer();
 | |
| 
 | |
|   _GpuTexture();
 | |
| 
 | |
|   create(int d, SessionID sessionId, FFI ffi) {
 | |
|     if (support) {
 | |
|       _sessionId = sessionId;
 | |
|       _display = d;
 | |
| 
 | |
|       gpuTextureRenderer.registerTexture().then((id) async {
 | |
|         _id = id;
 | |
|         if (id != null) {
 | |
|           _textureId = id;
 | |
|           ffi.textureModel.setGpuTextureId(display: d, id: id);
 | |
|           final output = await gpuTextureRenderer.output(id);
 | |
|           _output = output;
 | |
|           if (output != null) {
 | |
|             platformFFI.registerGpuTexture(sessionId, d, output);
 | |
|           }
 | |
|           debugPrint(
 | |
|               "create gpu texture: peerId: ${ffi.id} display:$_display, textureId:$id, output:$output");
 | |
|         }
 | |
|       }, onError: (err) {
 | |
|         debugPrint("Failed to register gpu texture:$err");
 | |
|       });
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   destroy(bool unregisterTexture, FFI ffi) async {
 | |
|     // must stop texture render, render unregistered texture cause crash
 | |
|     if (!_destroying && support && _sessionId != null && _textureId != -1) {
 | |
|       _destroying = true;
 | |
|       if (unregisterTexture) {
 | |
|         platformFFI.registerGpuTexture(_sessionId!, _display, 0);
 | |
|         // sleep for a while to avoid the texture is used after it's unregistered.
 | |
|         await Future.delayed(Duration(milliseconds: 100));
 | |
|       }
 | |
|       await gpuTextureRenderer.unregisterTexture(_textureId);
 | |
|       _textureId = -1;
 | |
|       _destroying = false;
 | |
|       debugPrint(
 | |
|           "destroy gpu texture: peerId: ${ffi.id} display:$_display, textureId:$_id, output:$_output");
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _Control {
 | |
|   RxInt textureID = (-1).obs;
 | |
| 
 | |
|   int _rgbaTextureId = -1;
 | |
|   int get rgbaTextureId => _rgbaTextureId;
 | |
|   int _gpuTextureId = -1;
 | |
|   int get gpuTextureId => _gpuTextureId;
 | |
|   bool _isGpuTexture = false;
 | |
|   bool get isGpuTexture => _isGpuTexture;
 | |
| 
 | |
|   setTextureType({bool gpuTexture = false}) {
 | |
|     _isGpuTexture = gpuTexture;
 | |
|     textureID.value = _isGpuTexture ? gpuTextureId : rgbaTextureId;
 | |
|   }
 | |
| 
 | |
|   setRgbaTextureId(int id) {
 | |
|     _rgbaTextureId = id;
 | |
|     textureID.value = _isGpuTexture ? gpuTextureId : rgbaTextureId;
 | |
|   }
 | |
| 
 | |
|   setGpuTextureId(int id) {
 | |
|     _gpuTextureId = id;
 | |
|     textureID.value = _isGpuTexture ? gpuTextureId : rgbaTextureId;
 | |
|   }
 | |
| }
 | |
| 
 | |
| class TextureModel {
 | |
|   final WeakReference<FFI> parent;
 | |
|   final Map<int, _Control> _control = {};
 | |
|   final Map<int, _PixelbufferTexture> _pixelbufferRenderTextures = {};
 | |
|   final Map<int, _GpuTexture> _gpuRenderTextures = {};
 | |
| 
 | |
|   TextureModel(this.parent);
 | |
| 
 | |
|   setTextureType({required int display, required bool gpuTexture}) {
 | |
|     debugPrint("setTextureType: display=$display, isGpuTexture=$gpuTexture");
 | |
|     ensureControl(display);
 | |
|     _control[display]?.setTextureType(gpuTexture: gpuTexture);
 | |
|     // For versions that do not support multiple displays, the display parameter is always 0, need set type of current display
 | |
|     final ffi = parent.target;
 | |
|     if (ffi == null) return;
 | |
|     if (!ffi.ffiModel.pi.isSupportMultiDisplay) {
 | |
|       final currentDisplay = CurrentDisplayState.find(ffi.id).value;
 | |
|       if (currentDisplay != display) {
 | |
|         debugPrint(
 | |
|             "setTextureType: currentDisplay=$currentDisplay, isGpuTexture=$gpuTexture");
 | |
|         ensureControl(currentDisplay);
 | |
|         _control[currentDisplay]?.setTextureType(gpuTexture: gpuTexture);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   setRgbaTextureId({required int display, required int id}) {
 | |
|     ensureControl(display);
 | |
|     _control[display]?.setRgbaTextureId(id);
 | |
|   }
 | |
| 
 | |
|   setGpuTextureId({required int display, required int id}) {
 | |
|     ensureControl(display);
 | |
|     _control[display]?.setGpuTextureId(id);
 | |
|   }
 | |
| 
 | |
|   RxInt getTextureId(int display) {
 | |
|     ensureControl(display);
 | |
|     return _control[display]!.textureID;
 | |
|   }
 | |
| 
 | |
|   updateCurrentDisplay(int curDisplay) {
 | |
|     final ffi = parent.target;
 | |
|     if (ffi == null) return;
 | |
|     tryCreateTexture(int idx) {
 | |
|       if (!_pixelbufferRenderTextures.containsKey(idx)) {
 | |
|         final renderTexture = _PixelbufferTexture();
 | |
|         _pixelbufferRenderTextures[idx] = renderTexture;
 | |
|         renderTexture.create(idx, ffi.sessionId, ffi);
 | |
|       }
 | |
|       if (!_gpuRenderTextures.containsKey(idx)) {
 | |
|         final renderTexture = _GpuTexture();
 | |
|         _gpuRenderTextures[idx] = renderTexture;
 | |
|         renderTexture.create(idx, ffi.sessionId, ffi);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     tryRemoveTexture(int idx) {
 | |
|       _control.remove(idx);
 | |
|       if (_pixelbufferRenderTextures.containsKey(idx)) {
 | |
|         _pixelbufferRenderTextures[idx]!.destroy(true, ffi);
 | |
|         _pixelbufferRenderTextures.remove(idx);
 | |
|       }
 | |
|       if (_gpuRenderTextures.containsKey(idx)) {
 | |
|         _gpuRenderTextures[idx]!.destroy(true, ffi);
 | |
|         _gpuRenderTextures.remove(idx);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (curDisplay == kAllDisplayValue) {
 | |
|       final displays = ffi.ffiModel.pi.getCurDisplays();
 | |
|       for (var i = 0; i < displays.length; i++) {
 | |
|         tryCreateTexture(i);
 | |
|       }
 | |
|     } else {
 | |
|       tryCreateTexture(curDisplay);
 | |
|       for (var i = 0; i < ffi.ffiModel.pi.displays.length; i++) {
 | |
|         if (i != curDisplay) {
 | |
|           tryRemoveTexture(i);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   onRemotePageDispose(bool closeSession) async {
 | |
|     final ffi = parent.target;
 | |
|     if (ffi == null) return;
 | |
|     for (final texture in _pixelbufferRenderTextures.values) {
 | |
|       await texture.destroy(closeSession, ffi);
 | |
|     }
 | |
|     for (final texture in _gpuRenderTextures.values) {
 | |
|       await texture.destroy(closeSession, ffi);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   ensureControl(int display) {
 | |
|     var ctl = _control[display];
 | |
|     if (ctl == null) {
 | |
|       ctl = _Control();
 | |
|       _control[display] = ctl;
 | |
|     }
 | |
|   }
 | |
| }
 |