From bdcbd90ec6a0c626aa77d22df8f35d70d5998832 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Mon, 4 Nov 2024 17:17:24 +0800 Subject: [PATCH] split D3D/GLES texture creation --- .../widgets/src/thermion_texture_widget.dart | 29 +- .../lib/thermion_flutter.dart | 1 + .../thermion_flutter/pubspec.yaml | 5 + .../thermion_flutter/windows/CMakeLists.txt | 67 +--- .../windows/flutter_egl_texture.cpp | 53 +++ .../windows/include/flutter_egl_texture.h | 29 ++ .../windows/rendering/egl/CMakeLists.txt | 21 - .../windows/rendering/egl/egl_context.cpp | 43 ++- .../windows/rendering/egl/egl_context.h | 13 +- .../windows/rendering/egl/egl_texture.cpp | 361 +++++++++++++++--- .../windows/rendering/egl/egl_texture.h | 9 +- .../windows/rendering/egl/main.cpp | 15 +- .../rendering/flutter_render_context.h | 23 -- .../rendering/flutter_texture_buffer.h | 25 -- .../windows/thermion_flutter_plugin.cpp | 63 ++- .../windows/thermion_flutter_plugin.h | 24 +- .../windows/thermion_flutter_plugin_c_api.cpp | 2 +- .../lib/src/platform_texture.dart | 211 +++++----- ...mion_flutter_method_channel_interface.dart | 77 ---- ...rmion_flutter_method_channel_platform.dart | 132 +++++++ ...rmion_flutter_texture_backed_platform.dart | 71 ---- .../lib/src/thermion_flutter_windows.dart | 208 +++++----- .../lib/thermion_flutter_ffi.dart | 2 +- .../thermion_flutter_ffi/pubspec.yaml | 12 +- .../thermion_flutter_platform_interface.dart | 29 +- .../lib/thermion_flutter_texture.dart | 18 +- 26 files changed, 897 insertions(+), 646 deletions(-) create mode 100644 thermion_flutter/thermion_flutter/windows/flutter_egl_texture.cpp create mode 100644 thermion_flutter/thermion_flutter/windows/include/flutter_egl_texture.h delete mode 100644 thermion_flutter/thermion_flutter/windows/rendering/flutter_render_context.h delete mode 100644 thermion_flutter/thermion_flutter/windows/rendering/flutter_texture_buffer.h delete mode 100644 thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_method_channel_interface.dart create mode 100644 thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_method_channel_platform.dart delete mode 100644 thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_texture_backed_platform.dart diff --git a/thermion_flutter/thermion_flutter/lib/src/widgets/src/thermion_texture_widget.dart b/thermion_flutter/thermion_flutter/lib/src/widgets/src/thermion_texture_widget.dart index 0f56dd3a..c5cce627 100644 --- a/thermion_flutter/thermion_flutter/lib/src/widgets/src/thermion_texture_widget.dart +++ b/thermion_flutter/thermion_flutter/lib/src/widgets/src/thermion_texture_widget.dart @@ -5,7 +5,6 @@ import 'package:thermion_dart/src/viewer/src/shared_types/view.dart' as t; import 'package:thermion_flutter/src/widgets/src/resize_observer.dart'; import 'package:thermion_flutter/thermion_flutter.dart'; import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart'; -import 'package:vector_math/vector_math_64.dart' hide Colors; class ThermionTextureWidget extends StatefulWidget { /// @@ -52,7 +51,10 @@ class _ThermionTextureWidgetState extends State { void dispose() { super.dispose(); _views.remove(widget.view); - _texture?.destroy(); + if(_texture != null) { + ThermionFlutterPlatform.instance.destroyTexture(_texture!); + } + _states.remove(this); } @@ -79,7 +81,10 @@ class _ThermionTextureWidgetState extends State { "Target texture dimensions ${width}x${height} (pixel ratio : $dpr)"); _texture = await ThermionFlutterPlatform.instance - .createTexture(widget.view, width, height); + .createTexture(width, height); + + await ThermionFlutterPlatform.instance + .bind(widget.view, _texture!); _logger.info( "Actual texture dimensions ${_texture!.width}x${_texture!.height} (pixel ratio : $dpr)"); @@ -109,7 +114,10 @@ class _ThermionTextureWidgetState extends State { if (mounted) { setState(() {}); } - await texture?.destroy(); + if(texture != null) { + ThermionFlutterPlatform.instance.destroyTexture(texture); + } + _views.clear(); }); }); @@ -124,7 +132,7 @@ class _ThermionTextureWidgetState extends State { /// /// Each instance of ThermionTextureWidget in the widget hierarchy must - /// call[markFrameAvailable] on every frame to notify Flutter that the content + /// call [markFrameAvailable] on every frame to notify Flutter that the content /// of its backing texture has changed. /// /// Calling [requestFrame] on [ThermionViewer], however, will render all @@ -149,7 +157,9 @@ class _ThermionTextureWidgetState extends State { await widget.viewer.requestFrame(); lastRender = d.inMilliseconds; } - await _texture?.markFrameAvailable(); + if(_texture != null) { + await ThermionFlutterPlatform.instance.markTextureFrameAvailable(_texture!); + } _rendering = false; } _requestFrame(); @@ -190,12 +200,7 @@ class _ThermionTextureWidgetState extends State { _logger.info( "Resizing texture to dimensions ${newWidth}x${newHeight} (pixel ratio : $dpr)"); - await _texture?.resize( - newWidth, - newHeight, - 0, - 0, - ); + await ThermionFlutterPlatform.instance.resizeTexture(_texture!, newWidth, newHeight); _logger.info( "Resized texture to dimensions ${_texture!.width}x${_texture!.height} (pixel ratio : $dpr)"); diff --git a/thermion_flutter/thermion_flutter/lib/thermion_flutter.dart b/thermion_flutter/thermion_flutter/lib/thermion_flutter.dart index 8d69510a..dd3a9f1e 100644 --- a/thermion_flutter/thermion_flutter/lib/thermion_flutter.dart +++ b/thermion_flutter/thermion_flutter/lib/thermion_flutter.dart @@ -3,4 +3,5 @@ library thermion_flutter; export 'src/thermion_flutter_plugin.dart'; export 'src/widgets/widgets.dart'; export 'package:thermion_flutter_platform_interface/thermion_flutter_platform_interface.dart'; +export 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart'; export 'package:thermion_dart/thermion_dart.dart'; diff --git a/thermion_flutter/thermion_flutter/pubspec.yaml b/thermion_flutter/thermion_flutter/pubspec.yaml index d224ac06..2e021f8e 100644 --- a/thermion_flutter/thermion_flutter/pubspec.yaml +++ b/thermion_flutter/thermion_flutter/pubspec.yaml @@ -24,6 +24,11 @@ dependencies: logging: ^1.2.0 web: ^1.0.0 +dependency_overrides: + thermion_flutter_ffi: + path: ../thermion_flutter_ffi + thermion_flutter_platform_interface: + path: ../thermion_flutter_platform_interface dev_dependencies: flutter_test: sdk: flutter diff --git a/thermion_flutter/thermion_flutter/windows/CMakeLists.txt b/thermion_flutter/thermion_flutter/windows/CMakeLists.txt index cfebf200..42f12753 100644 --- a/thermion_flutter/thermion_flutter/windows/CMakeLists.txt +++ b/thermion_flutter/thermion_flutter/windows/CMakeLists.txt @@ -4,31 +4,16 @@ project(${PROJECT_NAME} LANGUAGES C CXX) cmake_policy(VERSION 3.14...3.25) -# This value is used when generating builds using this plugin, so it must -# not be changed set(PLUGIN_NAME "thermion_flutter_plugin") -# Any new source files that you add to the plugin should be added here. list(APPEND PLUGIN_SOURCES "thermion_flutter_plugin.cpp" "thermion_flutter_plugin.h" + "flutter_egl_texture.cpp" ) -set(THERMION_EGL FALSE) -set(WGL_USE_BACKING_WINDOW FALSE) +add_subdirectory("rendering/egl") -if(THERMION_EGL) - add_compile_definitions(THERMION_EGL) - list(APPEND PLUGIN_SOURCES "flutter_angle_texture.cpp" "egl_context.cpp" ) -else() - if(WGL_USE_BACKING_WINDOW) - add_compile_definitions(WGL_USE_BACKING_WINDOW) - endif() - list(APPEND PLUGIN_SOURCES "wgl_context.cpp" "opengl_texture_buffer.cpp" "backing_window.cpp") -endif() - -# Define the plugin library target. Its name must not be changed (see comment -# on PLUGIN_NAME above). add_library(${PLUGIN_NAME} SHARED "include/thermion_flutter/thermion_flutter_plugin_c_api.h" "thermion_flutter_plugin_c_api.cpp" @@ -45,37 +30,12 @@ target_compile_features(${PLUGIN_NAME} PUBLIC cxx_std_20) target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) target_include_directories(${PLUGIN_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}" ) include_directories( "${CMAKE_SOURCE_DIR}/../../../../thermion_dart/native/include/filament" "${CMAKE_SOURCE_DIR}/../../../../thermion_dart/native/include" -) - -if(THERMION_EGL) - list(APPEND GL_LIBS - EGL - GLESv2 - ) - set(ANGLE_OR_OPENGL_DIR angle) - add_library(EGL SHARED IMPORTED) - set_property(TARGET EGL PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_SOURCE_DIR}/../../../../thermion_dart/native/lib/windows/x86_64/mdd/libEGL.dll.lib") - set_property(TARGET EGL PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_SOURCE_DIR}/../../../../thermion_dart/native/lib/windows/x86_64/mt/angle/libEGL.dll.lib") - set_property(TARGET EGL PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_SOURCE_DIR}/../../../../thermion_dart/native/lib/windows/x86_64/mt/angle/libEGL.dll.lib") - add_library(GLESv2 SHARED IMPORTED) - set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_SOURCE_DIR}/../../../../thermion_dart/native/lib/windows/x86_64/mdd/libGLESv2.dll.lib") - set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_SOURCE_DIR}/../../../../thermion_dart/native/lib/windows/x86_64/mt/angle/libGLESv2.dll.lib") - set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_SOURCE_DIR}/../../../../thermion_dart/native/lib/windows/x86_64/mt/angle/libGLESv2.dll.lib") -else() - list(APPEND GL_LIBS - opengl32 - dwmapi - comctl32 - ) - set(ANGLE_OR_OPENGL_DIR opengl) -endif() - -include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include ) @@ -83,24 +43,19 @@ target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin Shlwapi - ${GL_LIBS} + thermion_egl ) -# List of absolute paths to libraries that should be bundled with the plugin -if(THERMION_EGL) -set(thermion_flutter_bundled_libraries - ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/angle/libEGL.dll - ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/angle/libGLESv2.dll - ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/libc++.dll - ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/third_party_abseil-cpp_absl.dll - ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/third_party_zlib.dll - ${CMAKE_CURRENT_SOURCE_DIR}/thermion_dart.dll - PARENT_SCOPE +# Copy thermion_egl library to the Flutter build directory +add_custom_command(TARGET ${PLUGIN_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ + $ ) -else() + set(thermion_flutter_bundled_libraries ${runner_BINARY_DIR}/../../../native_assets/windows/thermion_dart.dll + $ PARENT_SCOPE ) -endif() diff --git a/thermion_flutter/thermion_flutter/windows/flutter_egl_texture.cpp b/thermion_flutter/thermion_flutter/windows/flutter_egl_texture.cpp new file mode 100644 index 00000000..1ce6fdab --- /dev/null +++ b/thermion_flutter/thermion_flutter/windows/flutter_egl_texture.cpp @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "flutter_egl_texture.h" + +namespace thermion::tflutter::windows +{ + + FlutterEGLTexture::FlutterEGLTexture(HANDLE d3dTexture2DHandle, uint32_t width, uint32_t height) : _width(width), _height(height) + { + _textureDescriptor = std::make_unique(); + _textureDescriptor->struct_size = sizeof(FlutterDesktopGpuSurfaceDescriptor); + _textureDescriptor->handle = d3dTexture2DHandle; + _textureDescriptor->width = _textureDescriptor->visible_width = width; + _textureDescriptor->height = _textureDescriptor->visible_height = height; + _textureDescriptor->release_context = nullptr; + _textureDescriptor->release_callback = [](void *release_context) { + + }; + _textureDescriptor->format = kFlutterDesktopPixelFormatBGRA8888; + + _texture = + std::make_unique<::flutter::TextureVariant>(::flutter::GpuSurfaceTexture::GpuSurfaceTexture( + kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle, + [&](size_t width, size_t height) + { + if (width != this->_width || height != this->_height) + { + //this->_onResizeRequested(width, height); + } + return _textureDescriptor.get(); + })); + } + + ::flutter::TextureVariant* FlutterEGLTexture::GetFlutterTexture() { + return _texture.get(); + } + + void FlutterEGLTexture::SetFlutterTextureId(int64_t textureId) { + _flutterTextureId = textureId; + } + + int64_t FlutterEGLTexture::GetFlutterTextureId() + { + return _flutterTextureId; + } + +} diff --git a/thermion_flutter/thermion_flutter/windows/include/flutter_egl_texture.h b/thermion_flutter/thermion_flutter/windows/include/flutter_egl_texture.h new file mode 100644 index 00000000..f227f3c9 --- /dev/null +++ b/thermion_flutter/thermion_flutter/windows/include/flutter_egl_texture.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace thermion::tflutter::windows { + + class FlutterEGLTexture { + public: + FlutterEGLTexture(HANDLE d3dTexture2DHandle, uint32_t width, uint32_t height); + ::flutter::TextureVariant* GetFlutterTexture(); + int64_t GetFlutterTextureId(); + void SetFlutterTextureId(int64_t textureId); + private: + uint32_t _width; + uint32_t _height; + std::unique_ptr _textureDescriptor = nullptr; + std::unique_ptr<::flutter::TextureVariant> _texture; + int64_t _flutterTextureId = -1; + }; +} + diff --git a/thermion_flutter/thermion_flutter/windows/rendering/egl/CMakeLists.txt b/thermion_flutter/thermion_flutter/windows/rendering/egl/CMakeLists.txt index e0d6820f..b07cf2d7 100644 --- a/thermion_flutter/thermion_flutter/windows/rendering/egl/CMakeLists.txt +++ b/thermion_flutter/thermion_flutter/windows/rendering/egl/CMakeLists.txt @@ -4,8 +4,6 @@ project(${PROJECT_NAME} LANGUAGES C CXX) cmake_policy(VERSION 3.14...3.25) -add_compile_definitions(THERMION_EGL) - set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) set(BUILD_SHARED_LIBS TRUE) set(CMAKE_ENABLE_EXPORTS TRUE) @@ -41,22 +39,3 @@ target_link_libraries(${PROJECT_NAME} PRIVATE d3d11 ) -# Test executable -add_executable(${PROJECT_NAME}_test - "main.cpp" -) - -# Make sure the test depends on the library -add_dependencies(${PROJECT_NAME}_test ${PROJECT_NAME}) - -target_link_libraries(${PROJECT_NAME}_test PRIVATE - ${PROJECT_NAME} -) - -# Copy ANGLE DLLs to the output directory -add_custom_command(TARGET ${PROJECT_NAME}_test POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "E:/angle/libEGL.dll" - "E:/angle/libGLESv2.dll" - "$" -) \ No newline at end of file diff --git a/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_context.cpp b/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_context.cpp index 808d8c2f..58efa0a2 100644 --- a/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_context.cpp +++ b/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_context.cpp @@ -6,7 +6,7 @@ namespace thermion::windows::egl { -FlutterEGLContext::FlutterEGLContext() { +ThermionEGLContext::ThermionEGLContext() { // D3D starts here IDXGIAdapter *adapter_ = nullptr; @@ -144,7 +144,7 @@ FlutterEGLContext::FlutterEGLContext() { } } -void FlutterEGLContext::CreateRenderingSurface( +EGLTexture* ThermionEGLContext::CreateRenderingSurface( uint32_t width, uint32_t height, uint32_t left, uint32_t top ) { @@ -152,17 +152,16 @@ void FlutterEGLContext::CreateRenderingSurface( // glext::importGLESExtensionsEntryPoints(); if(left != 0 || top != 0) { - // result->Error("ERROR", - // "Rendering with EGL uses a Texture render target/Flutter widget and does not need a window offset."); - return; + std::cout << "ERROR Rendering with EGL uses a Texture render target/Flutter widget and does not need a window offset." << std::endl; + return nullptr; } - if (_active.get()) { - // result->Error("ERROR", - // "Texture already exists. You must call destroyTexture before " - // "attempting to create a new one."); - return; - } + //if (_active && _active.get()) { + // // result->Error("ERROR", + // // "Texture already exists. You must call destroyTexture before " + // // "attempting to create a new one."); + // return nullptr; + //} _active = std::make_unique( width, height, @@ -176,17 +175,25 @@ void FlutterEGLContext::CreateRenderingSurface( // this->_channel->InvokeMethod("resize", std::move(val), nullptr); }); + return _active.get(); } -void FlutterEGLContext::RenderCallback() { - if(_active.get()) { - ((EGLTexture*)_active.get())->RenderCallback(); - } -} - -void* FlutterEGLContext::GetSharedContext() { +void* ThermionEGLContext::GetSharedContext() { return (void*)_context; } +void ThermionEGLContext::ResizeRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top) { + +} + +void ThermionEGLContext::DestroyRenderingSurface() { + +} + +EGLTexture *ThermionEGLContext::GetActiveTexture() { + return _active.get(); +} + + } diff --git a/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_context.h b/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_context.h index 186bb081..0e5d39cf 100644 --- a/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_context.h +++ b/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_context.h @@ -7,12 +7,15 @@ namespace thermion::windows::egl { -class FlutterEGLContext { +class ThermionEGLContext { public: - FlutterEGLContext(); + ThermionEGLContext(); void* GetSharedContext(); - void RenderCallback(); - void CreateRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top); + EGLTexture * CreateRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top); + void DestroyRenderingSurface(); + void ResizeRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top); + + EGLTexture * GetActiveTexture(); private: void* _context = nullptr; @@ -20,7 +23,7 @@ private: EGLDisplay _eglDisplay = NULL; ID3D11Device* _D3D11Device = nullptr; ID3D11DeviceContext* _D3D11DeviceContext = nullptr; - std::unique_ptr _active; + std::unique_ptr _active = nullptr; }; } diff --git a/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_texture.cpp b/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_texture.cpp index 7364469b..dbc1efd8 100644 --- a/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_texture.cpp +++ b/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_texture.cpp @@ -59,21 +59,25 @@ static void logEglError(const char *name) noexcept { std::cout << name << " failed with " << err << std::endl; } -void EGLTexture::RenderCallback() { - glFinish(); - _D3D11DeviceContext->Flush(); +void EGLTexture::Flush() { + // glFlush(); // Ensure GL commands are completed + // _D3D11DeviceContext->Flush(); +} + +HANDLE EGLTexture::GetTextureHandle() { + return _d3dTexture2DHandle; } EGLTexture::~EGLTexture() { - if (_eglDisplay != EGL_NO_DISPLAY && _eglSurface != EGL_NO_SURFACE) { - eglReleaseTexImage(_eglDisplay, _eglSurface, EGL_BACK_BUFFER); - } - auto success = eglDestroySurface(this->_eglDisplay, this->_eglSurface); - if(success != EGL_TRUE) { - std::cout << "Failed to destroy EGL Surface" << std::endl; - } + // if (_eglDisplay != EGL_NO_DISPLAY && _eglSurface != EGL_NO_SURFACE) { + // eglReleaseTexImage(_eglDisplay, _eglSurface, EGL_BACK_BUFFER); + // } + // auto success = eglDestroySurface(this->_eglDisplay, this->_eglSurface); + // if(success != EGL_TRUE) { + // std::cout << "Failed to destroy EGL Surface" << std::endl; + // } _d3dTexture2D->Release(); - glDeleteTextures(1, &this->glTextureId); + // glDeleteTextures(1, &this->glTextureId); } EGLTexture::EGLTexture( @@ -104,7 +108,7 @@ EGLTexture::EGLTexture( auto hr = _D3D11Device->CreateTexture2D(&d3d11_texture2D_desc, nullptr, &_d3dTexture2D); if FAILED (hr) { - // result->Error("ERROR", "Failed to create D3D texture", nullptr); + std::cout << "Failed to create D3D texture" << std::endl; return; ; } @@ -112,21 +116,39 @@ EGLTexture::EGLTexture( hr = _d3dTexture2D.As(&resource); if FAILED (hr) { - // result->Error("ERROR", "Failed to create D3D texture", nullptr); + std::cout << "Failed to create D3D texture" << std::endl; return; ; } hr = resource->GetSharedHandle(&_d3dTexture2DHandle); if FAILED (hr) { - // result->Error("ERROR", - // "Failed to get shared handle to external D3D texture", - // nullptr); + std::cout << "Failed to get shared handle to external D3D texture" << std::endl; return; ; } _d3dTexture2D->AddRef(); - std::cout << "Created external D3D texture" << std::endl; + std::cout << "Created external D3D texture " << width << "x" << height << std::endl; + + // Create render target view of the texture + ID3D11RenderTargetView* rtv = nullptr; + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = 0; + + hr = _D3D11Device->CreateRenderTargetView(_d3dTexture2D.Get(), &rtvDesc, &rtv); + if (FAILED(hr)) { + std::cout << "Failed to create render target view" << std::endl; + return; + } + + // Clear the texture to blue + float blueColor[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; // RGBA + _D3D11DeviceContext->ClearRenderTargetView(rtv, blueColor); + _D3D11DeviceContext->Flush(); + + std::cout << "Filled D3D texture blue" << std::endl; EGLint pbufferAttribs[] = { EGL_WIDTH, width, EGL_HEIGHT, height, @@ -144,25 +166,168 @@ EGLTexture::EGLTexture( return; } - glGenTextures(1, &glTextureId); + /****************** + * + * + * THis is working + * + * + */ + // // Clear to purple + // glClearColor(0.5f, 0.0f, 0.5f, 1.0f); + // glClear(GL_COLOR_BUFFER_BIT); - if (glTextureId == 0) { - std::cout - << "Failed to generate OpenGL texture for ANGLE, OpenGL err was %d", - glGetError(); + // // Present the surface + // eglSwapBuffers(_eglDisplay, _eglSurface); + + // // Synchronize + // glFlush(); + + + if (!eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglContext)) { + logEglError("eglMakeCurrent"); return; } - glBindTexture(GL_TEXTURE_2D, glTextureId); - eglBindTexImage(_eglDisplay, _eglSurface, EGL_BACK_BUFFER); + // Create and setup shaders for rendering the texture + const char* vertexShaderSource = R"(#version 300 es + precision mediump float; + in vec2 position; + in vec2 texcoord; + out vec2 v_texcoord; + void main() { + gl_Position = vec4(position, 0.0, 1.0); + v_texcoord = texcoord; + } + )"; + + const char* fragmentShaderSource = R"(#version 300 es + precision mediump float; + in vec2 v_texcoord; + uniform sampler2D u_texture; + out vec4 fragColor; + void main() { + fragColor = texture(u_texture, v_texcoord); + } + )"; + + // Create and compile vertex shader + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr); + glCompileShader(vertexShader); + + // Check vertex shader compilation + GLint success; + GLchar infoLog[512]; + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); + if (!success) { + glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog); + std::cout << "Vertex shader compilation failed:\n" << infoLog << std::endl; + } + + // Create and compile fragment shader + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr); + glCompileShader(fragmentShader); + + // Check fragment shader compilation + glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); + if (!success) { + glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog); + std::cout << "Fragment shader compilation failed:\n" << infoLog << std::endl; + } + + // Create shader program + GLuint shaderProgram = glCreateProgram(); + glAttachShader(shaderProgram, vertexShader); + glAttachShader(shaderProgram, fragmentShader); + glLinkProgram(shaderProgram); + + // Check program linking + glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); + if (!success) { + glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog); + std::cout << "Shader program linking failed:\n" << infoLog << std::endl; + } + + // Create the source texture + GLuint sourceTexture; + glGenTextures(1, &sourceTexture); + glBindTexture(GL_TEXTURE_2D, sourceTexture); + + // Fill texture with purple color + uint8_t purplePixels[] = { + 128, 0, 128, 255 // Single purple pixel (RGBA) + }; + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, purplePixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - // clearGlError - GLenum const error = glGetError(); - if (error != GL_NO_ERROR) { - std::cout << "Ignoring pending GL error " << error << std::endl; + // Create vertex buffer for fullscreen quad + float vertices[] = { + // Position // Texcoords + -1.0f, -1.0f, 0.0f, 0.0f, // Bottom left + 1.0f, -1.0f, 1.0f, 0.0f, // Bottom right + -1.0f, 1.0f, 0.0f, 1.0f, // Top left + 1.0f, 1.0f, 1.0f, 1.0f // Top right + }; + + GLuint vbo; + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + // Setup vertex attributes + glUseProgram(shaderProgram); + GLint posAttrib = glGetAttribLocation(shaderProgram, "position"); + GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord"); + + if (posAttrib < 0 || texAttrib < 0) { + std::cout << "Failed to get attribute locations. position: " << posAttrib + << " texcoord: " << texAttrib << std::endl; } + + glEnableVertexAttribArray(posAttrib); + glEnableVertexAttribArray(texAttrib); + + glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); + glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); + + // Set texture uniform + GLint texUniform = glGetUniformLocation(shaderProgram, "u_texture"); + glUniform1i(texUniform, 0); // Use texture unit 0 + + // Clear and render + glViewport(0, 0, width, height); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw the fullscreen quad + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + // Present the result + eglSwapBuffers(_eglDisplay, _eglSurface); + + glFlush(); + + // // Cleanup + // glDeleteBuffers(1, &vbo); + // glDeleteProgram(shaderProgram); + // glDeleteShader(vertexShader); + // glDeleteShader(fragmentShader); + // glDeleteTextures(1, &sourceTexture); + + // Check for errors + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + std::cout << "GL error after rendering: " << error << std::endl; + } + + std::cout << "FINISHED TEXTURE CREATION AND RENDERING" << std::endl; + + _D3D11DeviceContext->Flush(); + char const *version; version = (char const *)glGetString(GL_VERSION); @@ -172,27 +337,127 @@ EGLTexture::EGLTexture( glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); - // _textureDescriptor = std::make_unique(); - // _textureDescriptor->struct_size = sizeof(FlutterDesktopGpuSurfaceDescriptor); - // _textureDescriptor->handle = _d3dTexture2DHandle; - // _textureDescriptor->width = _textureDescriptor->visible_width = width; - // _textureDescriptor->height = _textureDescriptor->visible_height = height; - // _textureDescriptor->release_context = nullptr; - // _textureDescriptor->release_callback = [](void *release_context) { - - // }; - // _textureDescriptor->format = kFlutterDesktopPixelFormatBGRA8888; - - // texture = - // std::make_unique(flutter::GpuSurfaceTexture( - // kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle, - // [&](size_t width, size_t height) { - // if(width != this->_width || height != this->_height) { - // this->_onResizeRequested(width, height); - // } - // return _textureDescriptor.get(); - // })); + std::cout << "FINISHED TEXTURE CREATION" << std::endl; } +void EGLTexture::FillBlueAndSaveToBMP(const char* filename) { + // Create render target view of the texture + ID3D11RenderTargetView* rtv = nullptr; + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = 0; + + HRESULT hr = _D3D11Device->CreateRenderTargetView(_d3dTexture2D.Get(), &rtvDesc, &rtv); + if (FAILED(hr)) { + std::cout << "Failed to create render target view" << std::endl; + return; + } + + // Clear the texture to blue + float blueColor[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; // RGBA + _D3D11DeviceContext->ClearRenderTargetView(rtv, blueColor); + + // Create staging texture for CPU read access + D3D11_TEXTURE2D_DESC stagingDesc = {}; + _d3dTexture2D->GetDesc(&stagingDesc); + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.BindFlags = 0; + stagingDesc.MiscFlags = 0; + + ID3D11Texture2D* stagingTexture = nullptr; + hr = _D3D11Device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture); + if (FAILED(hr)) { + rtv->Release(); + std::cout << "Failed to create staging texture" << std::endl; + return; + } + + // Copy to staging texture + _D3D11DeviceContext->CopyResource(stagingTexture, _d3dTexture2D.Get()); + + // Save to BMP + bool success = SaveTextureAsBMP(stagingTexture, filename); + + // Cleanup + stagingTexture->Release(); + rtv->Release(); + + if (success) { + std::cout << "Successfully saved texture to " << filename << std::endl; + } +} + +bool EGLTexture::SaveTextureAsBMP(ID3D11Texture2D* texture, const char* filename) { + D3D11_TEXTURE2D_DESC desc; + texture->GetDesc(&desc); + + // Map texture to get pixel data + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT hr = _D3D11DeviceContext->Map(texture, 0, D3D11_MAP_READ, 0, &mappedResource); + if (FAILED(hr)) { + std::cout << "Failed to map texture" << std::endl; + return false; + } + + // BMP file header + #pragma pack(push, 1) + struct BMPHeader { + uint16_t signature; + uint32_t fileSize; + uint32_t reserved; + uint32_t dataOffset; + uint32_t headerSize; + int32_t width; + int32_t height; + uint16_t planes; + uint16_t bitsPerPixel; + uint32_t compression; + uint32_t imageSize; + int32_t xPixelsPerMeter; + int32_t yPixelsPerMeter; + uint32_t totalColors; + uint32_t importantColors; + }; + #pragma pack(pop) + + // Create and fill header + BMPHeader header = {}; + header.signature = 0x4D42; // 'BM' + header.fileSize = sizeof(BMPHeader) + desc.Width * desc.Height * 4; + header.dataOffset = sizeof(BMPHeader); + header.headerSize = 40; + header.width = desc.Width; + header.height = desc.Height; + header.planes = 1; + header.bitsPerPixel = 32; + header.compression = 0; + header.imageSize = desc.Width * desc.Height * 4; + header.xPixelsPerMeter = 2835; // 72 DPI + header.yPixelsPerMeter = 2835; // 72 DPI + + // Write to file + FILE* file = nullptr; + fopen_s(&file, filename, "wb"); + if (!file) { + _D3D11DeviceContext->Unmap(texture, 0); + return false; + } + + fwrite(&header, sizeof(header), 1, file); + + // Write pixel data (need to flip rows as BMP is bottom-up) + uint8_t* srcData = reinterpret_cast(mappedResource.pData); + for (int y = desc.Height - 1; y >= 0; y--) { + uint8_t* rowData = srcData + y * mappedResource.RowPitch; + fwrite(rowData, desc.Width * 4, 1, file); + } + + fclose(file); + _D3D11DeviceContext->Unmap(texture, 0); + return true; +} + } // namespace thermion_flutter \ No newline at end of file diff --git a/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_texture.h b/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_texture.h index afca6784..649d1453 100644 --- a/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_texture.h +++ b/thermion_flutter/thermion_flutter/windows/rendering/egl/egl_texture.h @@ -34,9 +34,14 @@ class EGLTexture { ); ~EGLTexture(); - void RenderCallback(); + void Flush(); + HANDLE GetTextureHandle(); GLuint glTextureId = 0; + + void FillBlueAndSaveToBMP(const char* filename); + bool SaveTextureAsBMP(ID3D11Texture2D* texture, const char* filename); + private: bool _error = false; @@ -57,8 +62,6 @@ class EGLTexture { EGLConfig _eglConfig = EGL_NO_CONFIG_KHR; EGLSurface _eglSurface = EGL_NO_SURFACE; - // std::unique_ptr _textureDescriptor = nullptr; - }; } diff --git a/thermion_flutter/thermion_flutter/windows/rendering/egl/main.cpp b/thermion_flutter/thermion_flutter/windows/rendering/egl/main.cpp index 848bdaa2..9e909b1c 100644 --- a/thermion_flutter/thermion_flutter/windows/rendering/egl/main.cpp +++ b/thermion_flutter/thermion_flutter/windows/rendering/egl/main.cpp @@ -6,14 +6,14 @@ int main() { std::cout << "Initializing EGL Context..." << std::endl; - thermion::windows::egl::FlutterEGLContext context; + thermion::windows::egl::ThermionEGLContext context; // Create a rendering surface const uint32_t width = 800; const uint32_t height = 600; std::cout << "Creating rendering surface " << width << "x" << height << std::endl; - context.CreateRenderingSurface(width, height, 0, 0); + auto *texture = context.CreateRenderingSurface(width, height, 0, 0); void* sharedContext = context.GetSharedContext(); if (sharedContext) { @@ -23,13 +23,10 @@ int main() { return 1; } - // Run a simple render loop - std::cout << "Starting render loop..." << std::endl; - for (int i = 0; i < 10; i++) { - context.RenderCallback(); - std::cout << "Rendered frame " << i + 1 << std::endl; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } + // Fill with blue and save + texture->FillBlueAndSaveToBMP("output.bmp"); + + std::cout << "Saved blue texture to output.bmp" << std::endl; std::cout << "EGL Context demo completed" << std::endl; return 0; diff --git a/thermion_flutter/thermion_flutter/windows/rendering/flutter_render_context.h b/thermion_flutter/thermion_flutter/windows/rendering/flutter_render_context.h deleted file mode 100644 index b7446cff..00000000 --- a/thermion_flutter/thermion_flutter/windows/rendering/flutter_render_context.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "flutter_texture_buffer.h" - -namespace thermion_flutter { - - class FlutterRenderContext { - public: - void CreateRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top); - void DestroyRenderingSurface(); - void *GetSharedContext(); - FlutterTextureBuffer GetActiveTexture() { - return _active->get(); - } - - protected: - FlutterRenderContext(); - std::unique_ptr _active = nullptr; - std::unique_ptr _inactive = nullptr; - }; -} - -#endif \ No newline at end of file diff --git a/thermion_flutter/thermion_flutter/windows/rendering/flutter_texture_buffer.h b/thermion_flutter/thermion_flutter/windows/rendering/flutter_texture_buffer.h deleted file mode 100644 index 62d2f9e0..00000000 --- a/thermion_flutter/thermion_flutter/windows/rendering/flutter_texture_buffer.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _FLUTTER_TEXTURE_BUFFER_H -#define _FLUTTER_TEXTURE_BUFFER_H - -#include -#include -#include -#include - -namespace thermion_flutter { - - class FlutterTextureBuffer { - public: - flutter::TextureVariant GetTexture() { - return texture->get(); - } - void RegisterFlutterTextureId(int64_t flutterTextureId); - int64_t GetFlutterTextureId(); - private: - int64_t flutterTextureId = -1; - std::unique_ptr texture; - - }; -} - -#endif \ No newline at end of file diff --git a/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin.cpp b/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin.cpp index 2feac132..f25d531d 100644 --- a/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin.cpp +++ b/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin.cpp @@ -27,15 +27,10 @@ #include #include -#include "flutter_render_context.h" +#include "flutter_egl_texture.h" +#include "rendering/egl/egl_context.h" -#if THERMION_EGL -#include "egl_context.h" -#else -#include "wgl_context.h" -#endif - -namespace thermion_flutter { +namespace thermion::tflutter::windows { using namespace std::chrono_literals; @@ -133,10 +128,16 @@ static void _freeResource(ResourceBuffer rbf, void *const plugin) { ((ThermionFlutterPlugin *)plugin)->freeResource(rbf); } +static std::unique_ptr _texture; + void ThermionFlutterPlugin::CreateTexture( const flutter::MethodCall &methodCall, std::unique_ptr> result) { + if (!_context) { + _context = std::make_unique(); + } + const auto *args = std::get_if(methodCall.arguments()); @@ -146,14 +147,17 @@ void ThermionFlutterPlugin::CreateTexture( int dTop = *(std::get_if(&(args->at(3)))); auto width = (uint32_t)round(dWidth ); auto height = (uint32_t)round(dHeight ); - auto left = (uint32_t)round(dLeft ); - auto top = (uint32_t)round(dTop ); + auto left = (uint32_t)round(dLeft); + auto top = (uint32_t)round(dTop); - _context->CreateRenderingSurface(width, height, std::move(result), left, top); - auto texture = _context->GetActiveTexture(); + thermion::windows::egl::EGLTexture* eglTexture = _context->CreateRenderingSurface(width, height, left, top); - auto flutterTextureId = _textureRegistrar->RegisterTexture(texture.GetFlutterTextureId()); - texture.RegisterFlutterTextureId(flutterTextureId); + _texture = std::make_unique(eglTexture->GetTextureHandle(), width, height); + + auto flutterTextureId = _textureRegistrar->RegisterTexture(_texture->GetFlutterTexture()); + _texture->SetFlutterTextureId(flutterTextureId); + auto glTextureId = 0; // _texture.GetGLTextureId(); + std::cout << "Registered Flutter texture ID " << flutterTextureId << std::endl; @@ -169,7 +173,8 @@ void ThermionFlutterPlugin::DestroyTexture( std::unique_ptr> result) { if (_context) { - _context->DestroyRenderingSurface(std::move(result)); + _context->DestroyRenderingSurface(); + result->Success(flutter::EncodableValue((int64_t)nullptr)); } else { result->Error("NO_CONTEXT", "No rendering context is active"); @@ -192,15 +197,11 @@ void ThermionFlutterPlugin::HandleMethodCall( result->Success(flutter::EncodableValue((int64_t)wrapper)); } else if(methodCall.method_name() == "getSharedContext") { if (!_context) { - #ifdef THERMION_EGL - _context = std::make_unique(_pluginRegistrar, _textureRegistrar); - #else - _context = std::make_unique(_pluginRegistrar, _textureRegistrar); - #endif + _context = std::make_unique(); } result->Success(flutter::EncodableValue((int64_t)_context->GetSharedContext())); } else if (methodCall.method_name() == "resizeWindow") { - #if WGL_USE_BACKING_WINDOW + const auto *args = std::get_if(methodCall.arguments()); @@ -215,9 +216,6 @@ void ThermionFlutterPlugin::HandleMethodCall( _context->ResizeRenderingSurface(width, height, left, top); result->Success(); - #else - result->Error("ERROR", "resizeWindow is only available when using a backing window"); - #endif } else if (methodCall.method_name() == "createTexture") { CreateTexture(methodCall, std::move(result)); } else if (methodCall.method_name() == "createWindow") { @@ -226,18 +224,17 @@ void ThermionFlutterPlugin::HandleMethodCall( DestroyTexture(methodCall, std::move(result)); } else if (methodCall.method_name() == "markTextureFrameAvailable") { if (_context) { - auto texture = context->GetActiveTexture(); - auto flutterTextureId = texture.GetFlutterTextureId(); - if(flutterTextureId == -1) { + + auto texture = _context->GetActiveTexture(); + texture->Flush(); + const auto* flutterTextureId = std::get_if(methodCall.arguments()); + + if(!flutterTextureId || *flutterTextureId == -1) { std::cout << "Bad texture" << std::endl; return; } - #ifdef THERMION_EGL - _context->RenderCallback(); - #endif - #if !WGL_USE_BACKING_WINDOW - _textureRegistrar->MarkTextureFrameAvailable(flutterTextureId); - #endif + std::cout << "Marking texture" << flutterTextureId << "available" << std::endl; + _textureRegistrar->MarkTextureFrameAvailable(*flutterTextureId); } result->Success(flutter::EncodableValue((int64_t)nullptr)); } else if (methodCall.method_name() == "getDriverPlatform") { diff --git a/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin.h b/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin.h index 2e220d48..8d04c1a7 100644 --- a/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin.h +++ b/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin.h @@ -1,5 +1,4 @@ -#ifndef FLUTTER_PLUGIN_FLUTTER_FILAMENT_PLUGIN_H_ -#define FLUTTER_PLUGIN_FLUTTER_FILAMENT_PLUGIN_H_ +#pragma once #include #include @@ -15,18 +14,13 @@ #include "GL/GLu.h" #include "ResourceBuffer.h" +#include "rendering/egl/egl_context.h" -#if THERMION_EGL -#include "egl_context.h" -#else -#include "wgl_context.h" -#endif +namespace thermion::tflutter::windows { -namespace thermion_flutter { - -class ThermionFlutterPlugin : public flutter::Plugin { +class ThermionFlutterPlugin : public ::flutter::Plugin { public: - static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); + static void RegisterWithRegistrar(::flutter::PluginRegistrarWindows *registrar); ThermionFlutterPlugin(flutter::TextureRegistrar *textureRegistrar, flutter::PluginRegistrarWindows *registrar, @@ -59,13 +53,9 @@ public: void freeResource(ResourceBuffer rbuf); private: - #ifdef THERMION_EGL - std::unique_ptr _context = nullptr; - #else - std::unique_ptr _context = nullptr; - #endif + std::unique_ptr _context = nullptr; }; } // namespace thermion_flutter -#endif // FLUTTER_PLUGIN_FLUTTER_FILAMENT_PLUGIN_H_ + diff --git a/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin_c_api.cpp b/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin_c_api.cpp index 2dc2c5e8..95ae763e 100644 --- a/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin_c_api.cpp +++ b/thermion_flutter/thermion_flutter/windows/thermion_flutter_plugin_c_api.cpp @@ -6,7 +6,7 @@ void ThermionFlutterPluginCApiRegisterWithRegistrar( FlutterDesktopPluginRegistrarRef registrar) { - thermion_flutter::ThermionFlutterPlugin::RegisterWithRegistrar( + thermion::tflutter::windows::ThermionFlutterPlugin::RegisterWithRegistrar( flutter::PluginRegistrarManager::GetInstance() ->GetRegistrar(registrar)); } diff --git a/thermion_flutter/thermion_flutter_ffi/lib/src/platform_texture.dart b/thermion_flutter/thermion_flutter_ffi/lib/src/platform_texture.dart index 408b5064..42c94a5f 100644 --- a/thermion_flutter/thermion_flutter_ffi/lib/src/platform_texture.dart +++ b/thermion_flutter/thermion_flutter_ffi/lib/src/platform_texture.dart @@ -1,122 +1,123 @@ -import 'package:logging/logging.dart'; -import 'package:thermion_dart/thermion_dart.dart'; -import 'thermion_flutter_method_channel_interface.dart'; +// import 'package:logging/logging.dart'; +// import 'package:thermion_dart/thermion_dart.dart'; +// import 'thermion_flutter_method_channel_interface.dart'; -class FlutterPlatformTexture extends MethodChannelFlutterTexture { - final _logger = Logger("ThermionFlutterTexture"); +// class FlutterPlatformTexture extends ThermionFlutterTexture { +// final _logger = Logger("ThermionFlutterTexture"); - final ThermionViewer viewer; - final View view; +// final ThermionViewer viewer; +// final View view; - int flutterId = -1; - int _lastFlutterId = -1; - int _lastHardwareId = -1; - int hardwareId = -1; - int width = -1; - int height = -1; +// int flutterId = -1; +// int _lastFlutterId = -1; +// int _lastHardwareId = -1; +// int hardwareId = -1; +// int width = -1; +// int height = -1; - SwapChain? swapChain; +// SwapChain? swapChain; - RenderTarget? _renderTarget; +// RenderTarget? _renderTarget; - late bool destroySwapChainOnResize; +// late bool destroySwapChainOnResize; - bool destroyed = false; +// bool destroyed = false; - FlutterPlatformTexture( - super.channel, this.viewer, this.view, this.swapChain) { - if (swapChain == null) { - destroySwapChainOnResize = true; - } else { - destroySwapChainOnResize = false; - } - } +// FlutterPlatformTexture( +// super.channel, this.viewer, this.view, this.swapChain) { +// if (swapChain == null) { +// destroySwapChainOnResize = true; +// } else { +// destroySwapChainOnResize = false; +// } +// } - @override - Future resize( - int newWidth, int newHeight, int newLeft, int newTop) async { - _logger.info( - "Resizing texture to $newWidth x $newHeight (offset $newLeft, $newTop)"); - if (newWidth == this.width && - newHeight == this.height && - newLeft == 0 && - newTop == 0) { - _logger.info("Existing texture matches requested dimensions"); - return; - } +// @override +// Future resize( +// int newWidth, int newHeight, int newLeft, int newTop) async { +// _logger.info( +// "Resizing texture to $newWidth x $newHeight (offset $newLeft, $newTop)"); +// if (newWidth == this.width && +// newHeight == this.height && +// newLeft == 0 && +// newTop == 0) { +// _logger.info("Existing texture matches requested dimensions"); +// return; +// } - this.width = newWidth; - this.height = newHeight; +// this.width = newWidth; +// this.height = newHeight; - var result = - await channel.invokeMethod("createTexture", [width, height, 0, 0]); - if (result == null || (result[0] == -1)) { - throw Exception("Failed to create texture"); - } - _lastFlutterId = flutterId; - _lastHardwareId = hardwareId; - flutterId = result[0] as int; - hardwareId = result[1] as int; +// var result = +// await channel.invokeMethod("createTexture", [width, height, 0, 0]); +// if (result == null || (result[0] == -1)) { +// throw Exception("Failed to create texture"); +// } +// _lastFlutterId = flutterId; +// _lastHardwareId = hardwareId; +// flutterId = result[0] as int; +// hardwareId = result[1] as int; +// var window = result[2] as int; // usually 0 for nullptr - _logger.info("Created texture ${flutterId} / ${hardwareId}"); +// _logger.info("Created texture ${flutterId} / ${hardwareId}"); - if (destroySwapChainOnResize) { - if (swapChain != null) { - await viewer.destroySwapChain(swapChain!); - } - swapChain = await viewer.createSwapChain(result[2]); - await view.setRenderable(true, swapChain!); - } else if (hardwareId != _lastHardwareId) { - if (_renderTarget != null) { - await viewer.destroyRenderTarget(_renderTarget!); - } - _renderTarget = - await viewer.createRenderTarget(width, height, hardwareId); - await view.setRenderTarget(_renderTarget!); - await view.setRenderable(true, swapChain!); - if (_lastFlutterId != -1 && _lastHardwareId != -1) { - await _destroyTexture(_lastFlutterId, _lastHardwareId); - _lastFlutterId = -1; - _lastHardwareId = -1; - } - } - } +// if (destroySwapChainOnResize) { +// if (swapChain != null) { +// await viewer.destroySwapChain(swapChain!); +// } +// swapChain = await viewer.createSwapChain(window); +// await view.setRenderable(true, swapChain!); +// } else if (hardwareId != _lastHardwareId) { +// if (_renderTarget != null) { +// await viewer.destroyRenderTarget(_renderTarget!); +// } +// _renderTarget = +// await viewer.createRenderTarget(width, height, hardwareId); +// await view.setRenderTarget(_renderTarget!); +// await view.setRenderable(true, swapChain!); +// if (_lastFlutterId != -1 && _lastHardwareId != -1) { +// await _destroyTexture(_lastFlutterId, _lastHardwareId); +// _lastFlutterId = -1; +// _lastHardwareId = -1; +// } +// } +// } - Future _destroyTexture( - int flutterTextureId, int hardwareTextureId) async { - try { - await channel.invokeMethod( - "destroyTexture", [flutterTextureId, hardwareTextureId]); - _logger.info("Destroyed texture $flutterTextureId / $hardwareTextureId"); - } catch (e) { - _logger.severe("Failed to destroy texture: $e"); - } - } +// Future _destroyTexture( +// int flutterTextureId, int hardwareTextureId) async { +// try { +// await channel.invokeMethod( +// "destroyTexture", [flutterTextureId, hardwareTextureId]); +// _logger.info("Destroyed texture $flutterTextureId / $hardwareTextureId"); +// } catch (e) { +// _logger.severe("Failed to destroy texture: $e"); +// } +// } - bool destroying = false; - Future destroy() async { - if (destroyed || destroying) { - return; - } - destroying = true; - await view.setRenderTarget(null); - if (_renderTarget != null) { - await viewer.destroyRenderTarget(_renderTarget!); - _renderTarget = null; - } +// bool destroying = false; +// Future destroy() async { +// if (destroyed || destroying) { +// return; +// } +// destroying = true; +// await view.setRenderTarget(null); +// if (_renderTarget != null) { +// await viewer.destroyRenderTarget(_renderTarget!); +// _renderTarget = null; +// } - if (destroySwapChainOnResize && swapChain != null) { - await viewer.destroySwapChain(swapChain!); - swapChain = null; - } - await _destroyTexture(flutterId, hardwareId); - flutterId = -1; - hardwareId = -1; - destroying = false; - destroyed = true; - } +// 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 { - await channel.invokeMethod("markTextureFrameAvailable", this.flutterId); - } -} +// Future markFrameAvailable() async { +// await channel.invokeMethod("markTextureFrameAvailable", this.flutterId); +// } +// } diff --git a/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_method_channel_interface.dart b/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_method_channel_interface.dart deleted file mode 100644 index 9abbc56f..00000000 --- a/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_method_channel_interface.dart +++ /dev/null @@ -1,77 +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_platform_interface/thermion_flutter_platform_interface.dart'; -import 'package:logging/logging.dart'; -import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart'; - -/// -/// An abstract implementation of [ThermionFlutterPlatform] that uses -/// Flutter platform channels to create a rendering context, -/// resource loaders, and surface/render target(s). -/// -abstract class ThermionFlutterMethodChannelInterface - extends ThermionFlutterPlatform { - final channel = const MethodChannel("dev.thermion.flutter/event"); - final _logger = Logger("ThermionFlutterMethodChannelInterface"); - - ThermionViewerFFI? viewer; - - Future createViewer({ThermionFlutterOptions? options}) async { - if (viewer != null) { - throw Exception( - "Only one ThermionViewer can be created at any given time; ensure you have called [dispose] on the previous instance before constructing a new instance."); - } - - var resourceLoader = Pointer.fromAddress( - await channel.invokeMethod("getResourceLoaderWrapper")); - - if (resourceLoader == nullptr) { - throw Exception("Failed to get resource loader"); - } - - var driverPlatform = await channel.invokeMethod("getDriverPlatform"); - var driverPtr = driverPlatform == null - ? nullptr - : Pointer.fromAddress(driverPlatform); - - var sharedContext = await channel.invokeMethod("getSharedContext"); - - var sharedContextPtr = sharedContext == null - ? nullptr - : Pointer.fromAddress(sharedContext); - - viewer = ThermionViewerFFI( - resourceLoader: resourceLoader, - driver: driverPtr, - sharedContext: sharedContextPtr, - uberArchivePath: options?.uberarchivePath); - await viewer!.initialized; - - viewer!.onDispose(() async { - this.viewer = null; - }); - - return viewer!; - } -} - -abstract class MethodChannelFlutterTexture extends ThermionFlutterTexture { - final MethodChannel channel; - - MethodChannelFlutterTexture(this.channel); - - @override - int get flutterId; - - @override - int get hardwareId; - - @override - int get height; - - @override - int get width; -} diff --git a/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_method_channel_platform.dart b/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_method_channel_platform.dart new file mode 100644 index 00000000..508141b1 --- /dev/null +++ b/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_method_channel_platform.dart @@ -0,0 +1,132 @@ +import 'dart:async'; +import 'dart:ffi'; +import 'dart:async'; +import 'dart:io'; +import 'package:flutter/services.dart'; +import 'package:thermion_dart/thermion_dart.dart'; +import 'package:thermion_dart/thermion_dart.dart' as t; +import 'package:thermion_flutter_ffi/src/thermion_flutter_method_channel_platform.dart'; +import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_interface.dart'; +import 'package:logging/logging.dart'; +import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart'; +import 'package:thermion_flutter_platform_interface/thermion_flutter_window.dart'; + +/// +/// An abstract implementation of [ThermionFlutterPlatform] that uses +/// Flutter platform channels to create a rendering context, +/// resource loaders, and surface/render target(s). +/// +class ThermionFlutterMethodChannelPlatform + extends ThermionFlutterPlatform { + + final channel = const MethodChannel("dev.thermion.flutter/event"); + final _logger = Logger("ThermionFlutterMethodChannelPlatform"); + + + static SwapChain? _swapChain; + + ThermionFlutterMethodChannelPlatform._(); + + static ThermionFlutterMethodChannelPlatform? instance; + + static void registerWith() { + instance ??= ThermionFlutterMethodChannelPlatform._(); + ThermionFlutterPlatform.instance = instance!; + } + + ThermionViewerFFI? viewer; + + Future createViewer({ThermionFlutterOptions? options}) async { + if (viewer != null) { + throw Exception( + "Only one ThermionViewer can be created at any given time; ensure you have called [dispose] on the previous instance before constructing a new instance."); + } + + var resourceLoader = Pointer.fromAddress( + await channel.invokeMethod("getResourceLoaderWrapper")); + + if (resourceLoader == nullptr) { + throw Exception("Failed to get resource loader"); + } + + var driverPlatform = await channel.invokeMethod("getDriverPlatform"); + var driverPtr = driverPlatform == null + ? nullptr + : Pointer.fromAddress(driverPlatform); + + var sharedContext = await channel.invokeMethod("getSharedContext"); + + var sharedContextPtr = sharedContext == null + ? nullptr + : Pointer.fromAddress(sharedContext); + + viewer = ThermionViewerFFI( + resourceLoader: resourceLoader, + driver: driverPtr, + sharedContext: sharedContextPtr, + uberArchivePath: options?.uberarchivePath); + await viewer!.initialized; + + viewer!.onDispose(() async { + _swapChain = null; + this.viewer = null; + }); + + if (_swapChain != null) { + throw Exception("Only a single swapchain can be created"); + } + + // this implementation renders directly into a texture/render target + // we still need to create a (headless) swapchain, but the actual dimensions + // don't matter + if (Platform.isMacOS || Platform.isIOS || Platform.isWindows) { + _swapChain = await viewer!.createHeadlessSwapChain(1, 1); + } + + return viewer!; + } + + Future createTexture(int width, int height) async { + var result = + await channel.invokeMethod("createTexture", [width, height, 0, 0]); + if (result == null || (result[0] == -1)) { + throw Exception("Failed to create texture"); + } + final flutterId = result[0] as int; + final hardwareId = result[1] as int; + var window = result[2] as int; // usually 0 for nullptr + + return ThermionFlutterTexture(flutterId:flutterId, hardwareId:hardwareId, height:height, width:width, window:window); + } + + @override + Future bind(view, ThermionFlutterTexture texture) { + // TODO: implement bind + throw UnimplementedError(); + } + + @override + Future createWindow(int width, int height, int offsetLeft, int offsetTop) { + // TODO: implement createWindow + throw UnimplementedError(); + } + + @override + Future destroyTexture(ThermionFlutterTexture texture) { + // TODO: implement destroyTexture + throw UnimplementedError(); + } + + @override + Future markTextureFrameAvailable(ThermionFlutterTexture texture) async { + await channel.invokeMethod("markTextureFrameAvailable", texture.flutterId); + } + + @override + Future resizeTexture(ThermionFlutterTexture texture, int width, int height) async { + return texture; + } + + +} + diff --git a/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_texture_backed_platform.dart b/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_texture_backed_platform.dart deleted file mode 100644 index 4c066e36..00000000 --- a/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_texture_backed_platform.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'dart:async'; -import 'dart:io'; - -import 'package:thermion_dart/thermion_dart.dart'; -import 'package:thermion_dart/thermion_dart.dart' as t; -import 'package:thermion_flutter_ffi/src/thermion_flutter_method_channel_interface.dart'; -import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_interface.dart'; -import 'package:logging/logging.dart'; -import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart'; -import 'package:thermion_flutter_platform_interface/thermion_flutter_window.dart'; - -import 'platform_texture.dart'; - -/// -/// An implementation of [ThermionFlutterPlatform] that uses -/// Flutter platform channels to create a rendering context, -/// resource loaders, and a texture that will be used as a render target -/// for a headless swapchain. -/// -class ThermionFlutterTextureBackedPlatform - extends ThermionFlutterMethodChannelInterface { - final _logger = Logger("ThermionFlutterTextureBackedPlatform"); - - static SwapChain? _swapChain; - - ThermionFlutterTextureBackedPlatform._(); - - static ThermionFlutterTextureBackedPlatform? instance; - - static void registerWith() { - instance ??= ThermionFlutterTextureBackedPlatform._(); - ThermionFlutterPlatform.instance = instance!; - } - - @override - Future createViewer({ThermionFlutterOptions? options}) async { - var viewer = await super.createViewer(options: options); - if (_swapChain != null) { - throw Exception("Only a single swapchain can be created"); - } - - // this implementation renders directly into a texture/render target - // we still need to create a (headless) swapchain, but the actual dimensions - // don't matter - if (Platform.isMacOS || Platform.isIOS || Platform.isWindows) { - _swapChain = await viewer.createHeadlessSwapChain(1, 1); - } - - viewer.onDispose(() async { - _swapChain = null; - }); - - return viewer; - } - - // On desktop platforms, textures are always created - Future createTexture( - t.View view, int width, int height) async { - var texture = FlutterPlatformTexture(channel, viewer!, view, - (Platform.isMacOS || Platform.isIOS || Platform.isWindows) ? _swapChain : null); - await texture.resize(width, height, 0, 0); - return texture; - } - - @override - Future createWindow( - int width, int height, int offsetLeft, int offsetTop) { - // TODO: implement createWindow - throw UnimplementedError(); - } -} diff --git a/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_windows.dart b/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_windows.dart index 306f7764..b7ee6819 100644 --- a/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_windows.dart +++ b/thermion_flutter/thermion_flutter_ffi/lib/src/thermion_flutter_windows.dart @@ -1,135 +1,135 @@ -import 'dart:async'; -import 'package:flutter/services.dart'; -import 'package:thermion_dart/thermion_dart.dart'; -import 'package:thermion_flutter_ffi/src/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'; -import 'package:thermion_flutter_platform_interface/thermion_flutter_window.dart'; +// import 'dart:async'; +// import 'package:flutter/services.dart'; +// import 'package:thermion_dart/thermion_dart.dart'; +// import 'package:thermion_flutter_ffi/src/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'; +// import 'package:thermion_flutter_platform_interface/thermion_flutter_window.dart'; -import 'platform_texture.dart'; +// import 'platform_texture.dart'; -/// -/// A Windows-only implementation of [ThermionFlutterPlatform] that uses -/// a Flutter platform channel to create a rendering context, -/// resource loader and a native HWND that will be sit behind the running -/// Flutter application. -/// -class ThermionFlutterWindows - extends ThermionFlutterMethodChannelInterface { +// /// +// /// A Windows-only implementation of [ThermionFlutterPlatform] that uses +// /// a Flutter platform channel to create a rendering context, +// /// resource loader and a native HWND that will be sit behind the running +// /// Flutter application. +// /// +// class ThermionFlutterWindows +// extends ThermionFlutterMethodChannelPlatform { - final _channel = const MethodChannel("dev.thermion.flutter/event"); +// final _channel = const MethodChannel("dev.thermion.flutter/event"); - final _logger = Logger("ThermionFlutterWindows"); +// final _logger = Logger("ThermionFlutterWindows"); - ThermionViewer? _viewer; +// ThermionViewer? _viewer; - SwapChain? _swapChain; +// SwapChain? _swapChain; - ThermionFlutterWindows._() {} +// ThermionFlutterWindows._() {} - static void registerWith() { - ThermionFlutterPlatform.instance = ThermionFlutterWindows._(); - } +// static void registerWith() { +// ThermionFlutterPlatform.instance = ThermionFlutterWindows._(); +// } - @override - Future createViewer({ThermionFlutterOptions? options}) async { - if(_viewer != null) { - throw Exception("Only one viewer should be instantiated over the life of the app"); - } - _viewer = await super.createViewer(options: options); - _viewer!.onDispose(() async { - _viewer = null; - }); - return _viewer!; - } +// @override +// Future createViewer({ThermionFlutterOptions? options}) async { +// if(_viewer != null) { +// throw Exception("Only one viewer should be instantiated over the life of the app"); +// } +// _viewer = await super.createViewer(options: options); +// _viewer!.onDispose(() async { +// _viewer = null; +// }); +// return _viewer!; +// } - /// - /// Not supported on Windows. Throws an exception. - /// - @override - Future createTexture(View view, int width, int height) async { - var texture = FlutterPlatformTexture(channel, viewer!, view, null); - await texture.resize(width, height, 0, 0); - return texture; - } +// /// +// /// Not supported on Windows. Throws an exception. +// /// +// @override +// Future createTexture(View view, int width, int height) async { +// var texture = FlutterPlatformTexture(channel, viewer!, view, null); +// await texture.resize(width, height, 0, 0); +// return texture; +// } - @override - Future createWindow(int width, int height, int offsetLeft, int offsetTop) async { +// @override +// Future createWindow(int width, int height, int offsetLeft, int offsetTop) async { - var result = await _channel - .invokeMethod("createWindow", [width, height, offsetLeft, offsetLeft]); +// var result = await _channel +// .invokeMethod("createWindow", [width, height, offsetLeft, offsetLeft]); - if (result == null || result[2] == -1) { - throw Exception("Failed to create window"); - } +// if (result == null || result[2] == -1) { +// throw Exception("Failed to create window"); +// } - var window = - ThermionFlutterWindowImpl(result[2], _channel, viewer!); - await window.resize(width, height, offsetLeft, offsetTop); - var view = await _viewer!.getViewAt(0); +// var window = +// ThermionFlutterWindowImpl(result[2], _channel, viewer!); +// await window.resize(width, height, offsetLeft, offsetTop); +// var view = await _viewer!.getViewAt(0); - await view.updateViewport(width, height); - _swapChain = await _viewer!.createSwapChain(window.handle); - await view.setRenderable(true, _swapChain!); - return window; - } +// await view.updateViewport(width, height); +// _swapChain = await _viewer!.createSwapChain(window.handle); +// await view.setRenderable(true, _swapChain!); +// return window; +// } -} +// } -class ThermionFlutterWindowImpl extends ThermionFlutterWindow { +// class ThermionFlutterWindowImpl extends ThermionFlutterWindow { - final ThermionViewer viewer; - final int handle; - int height = 0; - int width = 0; - int offsetLeft = 0; - int offsetTop = 0; - final MethodChannel _channel; +// final ThermionViewer viewer; +// final int handle; +// int height = 0; +// int width = 0; +// int offsetLeft = 0; +// int offsetTop = 0; +// final MethodChannel _channel; - ThermionFlutterWindowImpl(this.handle, this._channel, this.viewer); +// ThermionFlutterWindowImpl(this.handle, this._channel, this.viewer); - @override - Future destroy() async { - await _channel - .invokeMethod("destroyWindow", this.handle); - } +// @override +// Future destroy() async { +// await _channel +// .invokeMethod("destroyWindow", this.handle); +// } - @override - Future markFrameAvailable() { - // TODO: implement markFrameAvailable - throw UnimplementedError(); - } +// @override +// Future markFrameAvailable() { +// // TODO: implement markFrameAvailable +// throw UnimplementedError(); +// } - bool _resizing = false; +// bool _resizing = false; - /// - /// Called by [ThermionWidget] to resize the window. Don't call this yourself. - /// - @override - Future resize( - int width, int height, int offsetLeft, int offsetTop) async { - if (_resizing) { - throw Exception("Resize underway"); - } +// /// +// /// Called by [ThermionWidget] to resize the window. Don't call this yourself. +// /// +// @override +// Future resize( +// int width, int height, int offsetLeft, int offsetTop) async { +// if (_resizing) { +// throw Exception("Resize underway"); +// } - if (width == this.width && height == this.height && this.offsetLeft == offsetLeft && this.offsetTop == offsetTop) { - return; - } +// if (width == this.width && height == this.height && this.offsetLeft == offsetLeft && this.offsetTop == offsetTop) { +// return; +// } - this.width = width; - this.height = height; - this.offsetLeft = offsetLeft; - this.offsetTop = offsetTop; +// this.width = width; +// this.height = height; +// this.offsetLeft = offsetLeft; +// this.offsetTop = offsetTop; - _resizing = true; +// _resizing = true; - await _channel - .invokeMethod("resizeWindow", [width, height, offsetLeft, offsetTop]); - _resizing = false; - } +// await _channel +// .invokeMethod("resizeWindow", [width, height, offsetLeft, offsetTop]); +// _resizing = false; +// } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/thermion_flutter/thermion_flutter_ffi/lib/thermion_flutter_ffi.dart b/thermion_flutter/thermion_flutter_ffi/lib/thermion_flutter_ffi.dart index 6771a5e7..f4aa33a1 100644 --- a/thermion_flutter/thermion_flutter_ffi/lib/thermion_flutter_ffi.dart +++ b/thermion_flutter/thermion_flutter_ffi/lib/thermion_flutter_ffi.dart @@ -1,3 +1,3 @@ library; export 'src/thermion_flutter_windows.dart'; -export 'src/thermion_flutter_texture_backed_platform.dart'; +export 'src/thermion_flutter_method_channel_platform.dart'; diff --git a/thermion_flutter/thermion_flutter_ffi/pubspec.yaml b/thermion_flutter/thermion_flutter_ffi/pubspec.yaml index 4aba6e5b..32f858dd 100644 --- a/thermion_flutter/thermion_flutter_ffi/pubspec.yaml +++ b/thermion_flutter/thermion_flutter_ffi/pubspec.yaml @@ -11,13 +11,13 @@ flutter: implements: thermion_flutter_platform_interface platforms: ios: - dartPluginClass: ThermionFlutterTextureBackedPlatform + dartPluginClass: ThermionFlutterMethodChannelPlatform android: - dartPluginClass: ThermionFlutterTextureBackedPlatform + dartPluginClass: ThermionFlutterMethodChannelPlatform macos: - dartPluginClass: ThermionFlutterTextureBackedPlatform + dartPluginClass: ThermionFlutterMethodChannelPlatform windows: - dartPluginClass: ThermionFlutterTextureBackedPlatform + dartPluginClass: ThermionFlutterMethodChannelPlatform dependencies: flutter: @@ -26,7 +26,9 @@ dependencies: thermion_flutter_platform_interface: ^0.2.1-dev.16 thermion_dart: ^0.2.1-dev.0.0.16 logging: ^1.2.0 - +dependency_overrides: + thermion_flutter_platform_interface: + path: ../thermion_flutter_platform_interface dev_dependencies: flutter_test: sdk: flutter diff --git a/thermion_flutter/thermion_flutter_platform_interface/lib/thermion_flutter_platform_interface.dart b/thermion_flutter/thermion_flutter_platform_interface/lib/thermion_flutter_platform_interface.dart index 4c8a6fd6..5b74d7ac 100644 --- a/thermion_flutter/thermion_flutter_platform_interface/lib/thermion_flutter_platform_interface.dart +++ b/thermion_flutter/thermion_flutter_platform_interface/lib/thermion_flutter_platform_interface.dart @@ -39,7 +39,34 @@ abstract class ThermionFlutterPlatform extends PlatformInterface { /// call this yourself. May not be supported on all platforms. /// Future createTexture( - t.View view, int width, int height); + int width, int height); + + /// + /// + /// + /// + Future resizeTexture( + ThermionFlutterTexture texture, + int width, int height); + + /// + /// + /// + Future destroyTexture(ThermionFlutterTexture texture); + + /// + /// + /// + Future markTextureFrameAvailable(ThermionFlutterTexture texture); + + /// + /// Binds a rendering surface to the given View. + /// + /// This is internal; unless you are [thermion_*] package developer, don't + /// call this yourself. May not be supported on all platforms. + /// + Future bind( + t.View view, ThermionFlutterTexture texture); /// /// Create a rendering window. diff --git a/thermion_flutter/thermion_flutter_platform_interface/lib/thermion_flutter_texture.dart b/thermion_flutter/thermion_flutter_platform_interface/lib/thermion_flutter_texture.dart index e1635990..5120ece8 100644 --- a/thermion_flutter/thermion_flutter_platform_interface/lib/thermion_flutter_texture.dart +++ b/thermion_flutter/thermion_flutter_platform_interface/lib/thermion_flutter_texture.dart @@ -1,17 +1,13 @@ -abstract class ThermionFlutterTexture { +class ThermionFlutterTexture { - int get width; - int get height; + final int width; + final int height; - int get flutterId; - int get hardwareId; + final int flutterId; + final int hardwareId; - /// - /// Destroy a texture and clean up the texture cache (if applicable). - /// - Future destroy(); + final int window; - Future resize(int width, int height, int left, int top); + ThermionFlutterTexture({required this.width, required this.height, required this.flutterId, required this.hardwareId, required this.window}); - Future markFrameAvailable(); }