From 74ee35bfcde790fabf21bd0bea1f87903b693ffa Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Fri, 7 Mar 2025 14:52:45 +0800 Subject: [PATCH] use render thread methods for Texture/Image/TextureSampler --- .../lib/src/viewer/src/ffi/src/callbacks.dart | 15 + .../src/viewer/src/ffi/src/ffi_texture.dart | 197 ++++++++- .../viewer/src/ffi/src/thermion_dart.g.dart | 403 +++++++++++++++++- .../src/viewer/src/shared_types/texture.dart | 7 - .../c_api/ThermionDartRenderThreadApi.h | 86 +++- thermion_dart/native/src/c_api/TTexture.cpp | 8 + .../src/c_api/ThermionDartRenderThreadApi.cpp | 394 ++++++++++++++--- 7 files changed, 1025 insertions(+), 85 deletions(-) diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/callbacks.dart b/thermion_dart/lib/src/viewer/src/ffi/src/callbacks.dart index 41f65a6a..9ed40923 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/callbacks.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/callbacks.dart @@ -71,6 +71,21 @@ Future withIntCallback( return completer.future; } +Future withUInt32Callback( + Function(Pointer>) func) async { + final completer = Completer(); + // ignore: prefer_function_declarations_over_variables + void Function(int) callback = (int result) { + completer.complete(result); + }; + final nativeCallable = + NativeCallable.listener(callback); + func.call(nativeCallable.nativeFunction); + await completer.future; + nativeCallable.close(); + return completer.future; +} + Future withCharPtrCallback( Function(Pointer)>>) func) async { diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_texture.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_texture.dart index 31aa127c..3bd20c76 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_texture.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_texture.dart @@ -9,26 +9,32 @@ class FFITexture extends Texture { FFITexture(this._engine, this.pointer); - Future setLinearImage(covariant FFILinearImage image, PixelDataFormat format, + Future setLinearImage(covariant FFILinearImage image, PixelDataFormat format, PixelDataType type) async { - final result = Texture_loadImage( + final result = await withBoolCallback((cb) { + Texture_loadImageRenderThread( _engine, pointer, image.pointer, TPixelDataFormat.values[format.index], - TPixelDataType.values[type.index]); + TPixelDataType.values[type.index], + cb); + }); + if (!result) { throw Exception("Failed to set linear image"); } } @override - Future dispose() async { - Engine_destroyTexture(_engine, pointer); + Future dispose() async { + await withVoidCallback((cb) { + Engine_destroyTextureRenderThread(_engine, pointer, cb); + }); } @override - Future generateMipmaps() { + Future generateMipmaps() { // TODO: implement generateMipmaps throw UnimplementedError(); } @@ -70,15 +76,16 @@ class FFITexture extends Texture { } @override - Future setExternalImage(externalImage) { + Future setExternalImage(externalImage) { // TODO: implement setExternalImage throw UnimplementedError(); } @override - Future setImage(int level, Uint8List buffer, int width, int height, + Future setImage(int level, Uint8List buffer, int width, int height, int channels, PixelDataFormat format, PixelDataType type) async { - final success = Texture_setImage( + final success = await withBoolCallback((cb) { + Texture_setImageRenderThread( _engine, pointer, level, @@ -88,14 +95,17 @@ class FFITexture extends Texture { height, channels, format.index, - type.index); + type.index, + cb); + }); + if (!success) { throw Exception("Failed to set image"); } } @override - Future setImage3D( + Future setImage3D( int level, int xOffset, int yOffset, @@ -111,7 +121,7 @@ class FFITexture extends Texture { } @override - Future setSubImage(int level, int xOffset, int yOffset, int width, int height, + Future setSubImage(int level, int xOffset, int yOffset, int width, int height, Uint8List buffer, PixelDataFormat format, PixelDataType type) { // TODO: implement setSubImage throw UnimplementedError(); @@ -123,23 +133,53 @@ class FFILinearImage extends LinearImage { FFILinearImage(this.pointer); - Future destroy() async { - Image_destroy(this.pointer); + static Future createEmpty(int width, int height, int channels) async { + final imagePtr = await withPointerCallback((cb) { + Image_createEmptyRenderThread(width, height, channels, cb); + }); + + return FFILinearImage(imagePtr); + } + + static Future decode(Uint8List data, [String name = "image"]) async { + final namePtr = name.toNativeUtf8(); + + try { + final imagePtr = await withPointerCallback((cb) { + Image_decodeRenderThread(data.address, data.lengthInBytes, namePtr.cast(), cb); + }); + + return FFILinearImage(imagePtr); + } finally { + calloc.free(namePtr); + } + } + + Future destroy() async { + await withVoidCallback((cb) { + Image_destroyRenderThread(this.pointer, cb); + }); } @override Future getChannels() async { - return Image_getChannels(pointer); + return await withUInt32Callback((cb) { + Image_getChannelsRenderThread(pointer, cb); + }); } @override Future getHeight() async { - return Image_getHeight(pointer); + return await withUInt32Callback((cb) { + Image_getHeightRenderThread(pointer, cb); + }); } @override Future getWidth() async { - return Image_getWidth(pointer); + return await withUInt32Callback((cb) { + Image_getWidthRenderThread(pointer, cb); + }); } @override @@ -147,7 +187,128 @@ class FFILinearImage extends LinearImage { final height = await getHeight(); final width = await getWidth(); final channels = await getChannels(); - final ptr = Image_getBytes(pointer); + + final ptr = await withPointerCallback((cb) { + Image_getBytesRenderThread(pointer, cb); + }); + return ptr.asTypedList(height * width * channels); } } + +// Add these to access TextureSampler functionality: + +class FFITextureSampler extends TextureSampler { + final Pointer pointer; + + FFITextureSampler(this.pointer); + + static Future create() async { + final samplerPtr = await withPointerCallback((cb) { + TextureSampler_createRenderThread(cb); + }); + + return FFITextureSampler(samplerPtr); + } + + // static Future createWithFiltering( + // SamplerMinFilter minFilter, + // SamplerMagFilter magFilter, + // SamplerWrapMode wrapS, + // SamplerWrapMode wrapT, + // SamplerWrapMode wrapR) async { + // final samplerPtr = await withPointerCallback((cb) { + // TextureSampler_createWithFilteringRenderThread( + // TSamplerMinFilter.values[minFilter.index], + // TSamplerMagFilter.values[magFilter.index], + // TSamplerWrapMode.values[wrapS.index], + // TSamplerWrapMode.values[wrapT.index], + // TSamplerWrapMode.values[wrapR.index], + // cb); + // }); + + // return FFITextureSampler(samplerPtr); + // } + + // static Future createWithComparison( + // SamplerCompareMode compareMode, + // SamplerCompareFunc compareFunc) async { + // final samplerPtr = await withPointerCallback((cb) { + // TextureSampler_createWithComparisonRenderThread( + // TSamplerCompareMode.values[compareMode.index], + // TTextureSamplerCompareFunc.values[compareFunc.index], + // cb); + // }); + + // return FFITextureSampler(samplerPtr); + // } + + // Future setMinFilter(SamplerMinFilter filter) async { + // await withVoidCallback((cb) { + // TextureSampler_setMinFilterRenderThread( + // pointer, + // TSamplerMinFilter.values[filter.index], + // cb); + // }); + // } + + // Future setMagFilter(SamplerMagFilter filter) async { + // await withVoidCallback((cb) { + // TextureSampler_setMagFilterRenderThread( + // pointer, + // TSamplerMagFilter.values[filter.index], + // cb); + // }); + // } + + // Future setWrapModeS(SamplerWrapMode mode) async { + // await withVoidCallback((cb) { + // TextureSampler_setWrapModeSRenderThread( + // pointer, + // TSamplerWrapMode.values[mode.index], + // cb); + // }); + // } + + // Future setWrapModeT(SamplerWrapMode mode) async { + // await withVoidCallback((cb) { + // TextureSampler_setWrapModeTRenderThread( + // pointer, + // TSamplerWrapMode.values[mode.index], + // cb); + // }); + // } + + // Future setWrapModeR(SamplerWrapMode mode) async { + // await withVoidCallback((cb) { + // TextureSampler_setWrapModeRRenderThread( + // pointer, + // TSamplerWrapMode.values[mode.index], + // cb); + // }); + // } + + Future setAnisotropy(double anisotropy) async { + await withVoidCallback((cb) { + TextureSampler_setAnisotropyRenderThread(pointer, anisotropy, cb); + }); + } + + // Future setCompareMode( + // SamplerCompareMode mode, SamplerCompareFunc func) async { + // await withVoidCallback((cb) { + // TextureSampler_setCompareModeRenderThread( + // pointer, + // TSamplerCompareMode.values[mode.index], + // TTextureSamplerCompareFunc.values[func.index], + // cb); + // }); + // } + + @override + Future dispose() async { + await withVoidCallback((cb) { + TextureSampler_destroyRenderThread(pointer, cb); + }); + } +} \ No newline at end of file diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart index d0dcef07..453cd782 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart @@ -663,14 +663,6 @@ external void get_bounding_box_to_out( ffi.Pointer maxY, ); -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true) -external void destroy_texture( - ffi.Pointer sceneManager, - ffi.Pointer texture, -); - @ffi.Native)>(isLeaf: true) external TViewport View_getViewport( ffi.Pointer view, @@ -1657,6 +1649,15 @@ void Engine_buildTextureRenderThread( onComplete, ); +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>)>(isLeaf: true) +external void Engine_destroyTextureRenderThread( + ffi.Pointer engine, + ffi.Pointer tTexture, + ffi.Pointer> onComplete, +); + @ffi.Native< ffi.Void Function( ffi.Pointer, @@ -2101,6 +2102,392 @@ external void AnimationManager_setMorphTargetWeightsRenderThread( ffi.Pointer> callback, ); +@ffi.Native< + ffi.Void Function( + ffi.Uint32, + ffi.Uint32, + ffi.Uint32, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer)>>)>(isLeaf: true) +external void Image_createEmptyRenderThread( + int width, + int height, + int channel, + ffi.Pointer)>> + onComplete, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Size, + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer)>>)>(isLeaf: true) +external void Image_decodeRenderThread( + ffi.Pointer data, + int length, + ffi.Pointer name, + ffi.Pointer)>> + onComplete, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer< + ffi + .NativeFunction)>>)>( + isLeaf: true) +external void Image_getBytesRenderThread( + ffi.Pointer tLinearImage, + ffi.Pointer)>> + onComplete, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, + ffi.Pointer>)>(isLeaf: true) +external void Image_destroyRenderThread( + ffi.Pointer tLinearImage, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, + ffi.Pointer>)>( + isLeaf: true) +external void Image_getWidthRenderThread( + ffi.Pointer tLinearImage, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, + ffi.Pointer>)>( + isLeaf: true) +external void Image_getHeightRenderThread( + ffi.Pointer tLinearImage, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, + ffi.Pointer>)>( + isLeaf: true) +external void Image_getChannelsRenderThread( + ffi.Pointer tLinearImage, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedInt, + ffi.UnsignedInt, + ffi.Pointer>)>( + symbol: "Texture_loadImageRenderThread", isLeaf: true) +external void _Texture_loadImageRenderThread( + ffi.Pointer tEngine, + ffi.Pointer tTexture, + ffi.Pointer tImage, + int bufferFormat, + int pixelDataType, + ffi.Pointer> onComplete, +); + +void Texture_loadImageRenderThread( + ffi.Pointer tEngine, + ffi.Pointer tTexture, + ffi.Pointer tImage, + TPixelDataFormat bufferFormat, + TPixelDataType pixelDataType, + ffi.Pointer> onComplete, +) => + _Texture_loadImageRenderThread( + tEngine, + tTexture, + tImage, + bufferFormat.value, + pixelDataType.value, + onComplete, + ); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ffi.Size, + ffi.Uint32, + ffi.Uint32, + ffi.Uint32, + ffi.Uint32, + ffi.Uint32, + ffi.Pointer>)>( + isLeaf: true) +external void Texture_setImageRenderThread( + ffi.Pointer tEngine, + ffi.Pointer tTexture, + int level, + ffi.Pointer data, + int size, + int width, + int height, + int channels, + int bufferFormat, + int pixelDataType, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction)>>)>( + isLeaf: true) +external void RenderTarget_getColorTextureRenderThread( + ffi.Pointer tRenderTarget, + ffi.Pointer)>> + onComplete, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer)>>)>(isLeaf: true) +external void TextureSampler_createRenderThread( + ffi.Pointer< + ffi.NativeFunction)>> + onComplete, +); + +@ffi.Native< + ffi.Void Function( + ffi.UnsignedInt, + ffi.UnsignedInt, + ffi.UnsignedInt, + ffi.UnsignedInt, + ffi.UnsignedInt, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer)>>)>( + symbol: "TextureSampler_createWithFilteringRenderThread", isLeaf: true) +external void _TextureSampler_createWithFilteringRenderThread( + int minFilter, + int magFilter, + int wrapS, + int wrapT, + int wrapR, + ffi.Pointer< + ffi.NativeFunction)>> + onComplete, +); + +void TextureSampler_createWithFilteringRenderThread( + TSamplerMinFilter minFilter, + TSamplerMagFilter magFilter, + TSamplerWrapMode wrapS, + TSamplerWrapMode wrapT, + TSamplerWrapMode wrapR, + ffi.Pointer< + ffi.NativeFunction)>> + onComplete, +) => + _TextureSampler_createWithFilteringRenderThread( + minFilter.value, + magFilter.value, + wrapS.value, + wrapT.value, + wrapR.value, + onComplete, + ); + +@ffi.Native< + ffi.Void Function( + ffi.UnsignedInt, + ffi.UnsignedInt, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer)>>)>( + symbol: "TextureSampler_createWithComparisonRenderThread", isLeaf: true) +external void _TextureSampler_createWithComparisonRenderThread( + int compareMode, + int compareFunc, + ffi.Pointer< + ffi.NativeFunction)>> + onComplete, +); + +void TextureSampler_createWithComparisonRenderThread( + TSamplerCompareMode compareMode, + TSamplerCompareFunc compareFunc, + ffi.Pointer< + ffi.NativeFunction)>> + onComplete, +) => + _TextureSampler_createWithComparisonRenderThread( + compareMode.value, + compareFunc.value, + onComplete, + ); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.UnsignedInt, + ffi.Pointer>)>( + symbol: "TextureSampler_setMinFilterRenderThread", isLeaf: true) +external void _TextureSampler_setMinFilterRenderThread( + ffi.Pointer sampler, + int filter, + ffi.Pointer> onComplete, +); + +void TextureSampler_setMinFilterRenderThread( + ffi.Pointer sampler, + TSamplerMinFilter filter, + ffi.Pointer> onComplete, +) => + _TextureSampler_setMinFilterRenderThread( + sampler, + filter.value, + onComplete, + ); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.UnsignedInt, + ffi.Pointer>)>( + symbol: "TextureSampler_setMagFilterRenderThread", isLeaf: true) +external void _TextureSampler_setMagFilterRenderThread( + ffi.Pointer sampler, + int filter, + ffi.Pointer> onComplete, +); + +void TextureSampler_setMagFilterRenderThread( + ffi.Pointer sampler, + TSamplerMagFilter filter, + ffi.Pointer> onComplete, +) => + _TextureSampler_setMagFilterRenderThread( + sampler, + filter.value, + onComplete, + ); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.UnsignedInt, + ffi.Pointer>)>( + symbol: "TextureSampler_setWrapModeSRenderThread", isLeaf: true) +external void _TextureSampler_setWrapModeSRenderThread( + ffi.Pointer sampler, + int mode, + ffi.Pointer> onComplete, +); + +void TextureSampler_setWrapModeSRenderThread( + ffi.Pointer sampler, + TSamplerWrapMode mode, + ffi.Pointer> onComplete, +) => + _TextureSampler_setWrapModeSRenderThread( + sampler, + mode.value, + onComplete, + ); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.UnsignedInt, + ffi.Pointer>)>( + symbol: "TextureSampler_setWrapModeTRenderThread", isLeaf: true) +external void _TextureSampler_setWrapModeTRenderThread( + ffi.Pointer sampler, + int mode, + ffi.Pointer> onComplete, +); + +void TextureSampler_setWrapModeTRenderThread( + ffi.Pointer sampler, + TSamplerWrapMode mode, + ffi.Pointer> onComplete, +) => + _TextureSampler_setWrapModeTRenderThread( + sampler, + mode.value, + onComplete, + ); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.UnsignedInt, + ffi.Pointer>)>( + symbol: "TextureSampler_setWrapModeRRenderThread", isLeaf: true) +external void _TextureSampler_setWrapModeRRenderThread( + ffi.Pointer sampler, + int mode, + ffi.Pointer> onComplete, +); + +void TextureSampler_setWrapModeRRenderThread( + ffi.Pointer sampler, + TSamplerWrapMode mode, + ffi.Pointer> onComplete, +) => + _TextureSampler_setWrapModeRRenderThread( + sampler, + mode.value, + onComplete, + ); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Double, + ffi.Pointer>)>(isLeaf: true) +external void TextureSampler_setAnisotropyRenderThread( + ffi.Pointer sampler, + double anisotropy, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.UnsignedInt, + ffi.UnsignedInt, + ffi.Pointer>)>( + symbol: "TextureSampler_setCompareModeRenderThread", isLeaf: true) +external void _TextureSampler_setCompareModeRenderThread( + ffi.Pointer sampler, + int mode, + int func, + ffi.Pointer> onComplete, +); + +void TextureSampler_setCompareModeRenderThread( + ffi.Pointer sampler, + TSamplerCompareMode mode, + TSamplerCompareFunc func, + ffi.Pointer> onComplete, +) => + _TextureSampler_setCompareModeRenderThread( + sampler, + mode.value, + func.value, + onComplete, + ); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, + ffi.Pointer>)>(isLeaf: true) +external void TextureSampler_destroyRenderThread( + ffi.Pointer sampler, + ffi.Pointer> onComplete, +); + @ffi.Native< ffi.Void Function(ffi.Pointer, EntityId, ffi.Pointer>)>( diff --git a/thermion_dart/lib/src/viewer/src/shared_types/texture.dart b/thermion_dart/lib/src/viewer/src/shared_types/texture.dart index 2d3ebdf8..08c4a133 100644 --- a/thermion_dart/lib/src/viewer/src/shared_types/texture.dart +++ b/thermion_dart/lib/src/viewer/src/shared_types/texture.dart @@ -426,10 +426,3 @@ abstract class LinearImage { Future getChannels(); } -class FFITextureSampler extends TextureSampler { - final Pointer pointer; - - FFITextureSampler(this.pointer); - @override - Future dispose() async {} -} diff --git a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h index 98c5ef5b..e61ac899 100644 --- a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h +++ b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h @@ -55,6 +55,7 @@ namespace thermion TTextureFormat format, void (*onComplete)(TTexture*) ); + EMSCRIPTEN_KEEPALIVE void Engine_destroyTextureRenderThread(TEngine *engine, TTexture* tTexture, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance *)); @@ -124,11 +125,8 @@ namespace thermion bool shadows, void (*callback)(EntityId)); EMSCRIPTEN_KEEPALIVE void SceneManager_removeLightRenderThread(TSceneManager *tSceneManager, EntityId entityId, void (*callback)()); - EMSCRIPTEN_KEEPALIVE void SceneManager_createCameraRenderThread(TSceneManager *tSceneManager, void (*callback)(TCamera *)); - EMSCRIPTEN_KEEPALIVE void SceneAsset_createInstanceRenderThread(TSceneAsset *asset, TMaterialInstance **tMaterialInstances, int materialInstanceCount, void (*callback)(TSceneAsset *)); - EMSCRIPTEN_KEEPALIVE void MaterialProvider_createMaterialInstanceRenderThread(TMaterialProvider *tMaterialProvider, TMaterialKey *tKey, void (*callback)(TMaterialInstance *)); EMSCRIPTEN_KEEPALIVE void SceneManager_destroyMaterialInstanceRenderThread(TSceneManager *tSceneManager, TMaterialInstance *tMaterialInstance, void (*callback)()); @@ -144,6 +142,88 @@ namespace thermion int numWeights, void (*callback)(bool)); + // Image methods + EMSCRIPTEN_KEEPALIVE void Image_createEmptyRenderThread(uint32_t width, uint32_t height, uint32_t channel, void (*onComplete)(TLinearImage *)); + EMSCRIPTEN_KEEPALIVE void Image_decodeRenderThread(uint8_t* data, size_t length, const char* name, void (*onComplete)(TLinearImage *)); + EMSCRIPTEN_KEEPALIVE void Image_getBytesRenderThread(TLinearImage *tLinearImage, void (*onComplete)(float *)); + EMSCRIPTEN_KEEPALIVE void Image_destroyRenderThread(TLinearImage *tLinearImage, void (*onComplete)()); + EMSCRIPTEN_KEEPALIVE void Image_getWidthRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t)); + EMSCRIPTEN_KEEPALIVE void Image_getHeightRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t)); + EMSCRIPTEN_KEEPALIVE void Image_getChannelsRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t)); + + // Texture methods + EMSCRIPTEN_KEEPALIVE void Texture_loadImageRenderThread(TEngine *tEngine, TTexture *tTexture, TLinearImage *tImage, TPixelDataFormat bufferFormat, TPixelDataType pixelDataType, void (*onComplete)(bool)); + EMSCRIPTEN_KEEPALIVE void Texture_setImageRenderThread( + TEngine *tEngine, + TTexture *tTexture, + uint32_t level, + uint8_t *data, + size_t size, + uint32_t width, + uint32_t height, + uint32_t channels, + uint32_t bufferFormat, + uint32_t pixelDataType, + void (*onComplete)(bool) + ); + EMSCRIPTEN_KEEPALIVE void RenderTarget_getColorTextureRenderThread(TRenderTarget *tRenderTarget, void (*onComplete)(TTexture *)); + + // TextureSampler methods + EMSCRIPTEN_KEEPALIVE void TextureSampler_createRenderThread(void (*onComplete)(TTextureSampler*)); + EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithFilteringRenderThread( + TSamplerMinFilter minFilter, + TSamplerMagFilter magFilter, + TSamplerWrapMode wrapS, + TSamplerWrapMode wrapT, + TSamplerWrapMode wrapR, + void (*onComplete)(TTextureSampler*) + ); + EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithComparisonRenderThread( + TSamplerCompareMode compareMode, + TSamplerCompareFunc compareFunc, + void (*onComplete)(TTextureSampler*) + ); + EMSCRIPTEN_KEEPALIVE void TextureSampler_setMinFilterRenderThread( + TTextureSampler* sampler, + TSamplerMinFilter filter, + void (*onComplete)() + ); + EMSCRIPTEN_KEEPALIVE void TextureSampler_setMagFilterRenderThread( + TTextureSampler* sampler, + TSamplerMagFilter filter, + void (*onComplete)() + ); + EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeSRenderThread( + TTextureSampler* sampler, + TSamplerWrapMode mode, + void (*onComplete)() + ); + EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeTRenderThread( + TTextureSampler* sampler, + TSamplerWrapMode mode, + void (*onComplete)() + ); + EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeRRenderThread( + TTextureSampler* sampler, + TSamplerWrapMode mode, + void (*onComplete)() + ); + EMSCRIPTEN_KEEPALIVE void TextureSampler_setAnisotropyRenderThread( + TTextureSampler* sampler, + double anisotropy, + void (*onComplete)() + ); + EMSCRIPTEN_KEEPALIVE void TextureSampler_setCompareModeRenderThread( + TTextureSampler* sampler, + TSamplerCompareMode mode, + TTextureSamplerCompareFunc func, + void (*onComplete)() + ); + EMSCRIPTEN_KEEPALIVE void TextureSampler_destroyRenderThread( + TTextureSampler* sampler, + void (*onComplete)() + ); + EMSCRIPTEN_KEEPALIVE void update_bone_matrices_render_thread(TSceneManager *sceneManager, EntityId asset, void (*callback)(bool)); EMSCRIPTEN_KEEPALIVE void set_bone_transform_render_thread( diff --git a/thermion_dart/native/src/c_api/TTexture.cpp b/thermion_dart/native/src/c_api/TTexture.cpp index 1c605db4..b36b208f 100644 --- a/thermion_dart/native/src/c_api/TTexture.cpp +++ b/thermion_dart/native/src/c_api/TTexture.cpp @@ -209,6 +209,14 @@ namespace thermion } } + EMSCRIPTEN_KEEPALIVE void TextureSampler_setAnisotropy( + TTextureSampler *sampler, + double anisotropy) + { + auto *textureSampler = reinterpret_cast(sampler); + textureSampler->setAnisotropy(static_cast(anisotropy)); + } + EMSCRIPTEN_KEEPALIVE void TextureSampler_setMagFilter( TTextureSampler *sampler, TSamplerMagFilter filter) diff --git a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp index 9fbb832e..d2fbb30c 100644 --- a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp +++ b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp @@ -292,7 +292,8 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTargetRenderThread(TViewer *tViewer, TRenderTarget *tRenderTarget, void (*onComplete)()) { + EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTargetRenderThread(TViewer *tViewer, TRenderTarget *tRenderTarget, void (*onComplete)()) + { std::packaged_task lambda( [=]() mutable { @@ -302,22 +303,32 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void Engine_buildTextureRenderThread(TEngine *engine, - uint32_t width, - uint32_t height, - uint8_t levels, - TTextureSamplerType sampler, - TTextureFormat format, - void (*onComplete)(TTexture*) -) { - std::packaged_task lambda( - [=]() mutable - { - auto texture = Engine_buildTexture(engine, width, height, levels, sampler, format); - onComplete(texture); - }); -auto fut = _rl->add_task(lambda); -} + EMSCRIPTEN_KEEPALIVE void Engine_buildTextureRenderThread(TEngine *engine, + uint32_t width, + uint32_t height, + uint8_t levels, + TTextureSamplerType sampler, + TTextureFormat format, + void (*onComplete)(TTexture *)) + { + std::packaged_task lambda( + [=]() mutable + { + auto texture = Engine_buildTexture(engine, width, height, levels, sampler, format); + onComplete(texture); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void Engine_destroyTextureRenderThread(TEngine *engine, TTexture* tTexture, void (*onComplete)()) { + std::packaged_task lambda( + [=]() mutable + { + Engine_destroyTexture(engine, tTexture); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *)) { @@ -397,8 +408,7 @@ auto fut = _rl->add_task(lambda); std::packaged_task lambda([=]() mutable { auto *sceneAsset = SceneManager_createGrid(tSceneManager, tMaterial); - callback(sceneAsset); - }); + callback(sceneAsset); }); auto fut = _rl->add_task(lambda); } @@ -480,7 +490,8 @@ auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void SceneManager_destroyMaterialInstanceRenderThread(TSceneManager *tSceneManager, TMaterialInstance *tMaterialInstance, void (*callback)()) { + EMSCRIPTEN_KEEPALIVE void SceneManager_destroyMaterialInstanceRenderThread(TSceneManager *tSceneManager, TMaterialInstance *tMaterialInstance, void (*callback)()) + { std::packaged_task lambda( [=] { @@ -562,8 +573,8 @@ auto fut = _rl->add_task(lambda); } EMSCRIPTEN_KEEPALIVE void Viewer_loadSkyboxRenderThread(TViewer *viewer, - const char *skyboxPath, - void (*onComplete)()) + const char *skyboxPath, + void (*onComplete)()) { std::packaged_task lambda([=] { @@ -577,8 +588,7 @@ auto fut = _rl->add_task(lambda); std::packaged_task lambda([=] { Viewer_removeSkybox(viewer); - onComplete(); - }); + onComplete(); }); auto fut = _rl->add_task(lambda); } @@ -591,8 +601,9 @@ auto fut = _rl->add_task(lambda); }); auto fut = _rl->add_task(lambda); } - - EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, bool enabled, double strength) { + + EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, bool enabled, double strength) + { std::packaged_task lambda( [=] { @@ -641,34 +652,36 @@ auto fut = _rl->add_task(lambda); } EMSCRIPTEN_KEEPALIVE void SceneManager_addLightRenderThread( - TSceneManager *tSceneManager, - uint8_t type, - float colour, - float intensity, - float posX, - float posY, - float posZ, - float dirX, - float dirY, - float dirZ, - float falloffRadius, - float spotLightConeInner, - float spotLightConeOuter, - float sunAngularRadius, - float sunHaloSize, - float sunHaloFallof, - bool shadows, - void (*callback)(EntityId entityId)) { -std::packaged_task lambda( + TSceneManager *tSceneManager, + uint8_t type, + float colour, + float intensity, + float posX, + float posY, + float posZ, + float dirX, + float dirY, + float dirZ, + float falloffRadius, + float spotLightConeInner, + float spotLightConeOuter, + float sunAngularRadius, + float sunHaloSize, + float sunHaloFallof, + bool shadows, + void (*callback)(EntityId entityId)) + { + std::packaged_task lambda( [=]() mutable { auto light = SceneManager_addLight(tSceneManager, type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, falloffRadius, spotLightConeInner, spotLightConeOuter, sunAngularRadius, sunHaloSize, sunHaloFallof, shadows); callback(light); }); auto fut = _rl->add_task(lambda); - } - - EMSCRIPTEN_KEEPALIVE void SceneManager_removeLightRenderThread(TSceneManager *tSceneManager, EntityId entityId, void (*callback)()) { + } + + EMSCRIPTEN_KEEPALIVE void SceneManager_removeLightRenderThread(TSceneManager *tSceneManager, EntityId entityId, void (*callback)()) + { std::packaged_task lambda( [=]() mutable { @@ -699,7 +712,7 @@ std::packaged_task lambda( }); auto fut = _rl->add_task(lambda); } - + EMSCRIPTEN_KEEPALIVE void SceneManager_destroyLightsRenderThread(TSceneManager *tSceneManager, void (*callback)()) { std::packaged_task lambda( @@ -751,4 +764,287 @@ std::packaged_task lambda( }); auto fut = _rl->add_task(lambda); } + + // Add these implementations to your ThermionDartRenderThreadApi.cpp file + + // Image methods + EMSCRIPTEN_KEEPALIVE void Image_createEmptyRenderThread(uint32_t width, uint32_t height, uint32_t channel, void (*onComplete)(TLinearImage *)) + { + std::packaged_task lambda( + [=]() mutable + { + auto image = Image_createEmpty(width, height, channel); + onComplete(image); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void Image_decodeRenderThread(uint8_t *data, size_t length, const char *name, void (*onComplete)(TLinearImage *)) + { + std::packaged_task lambda( + [=]() mutable + { + auto image = Image_decode(data, length, name); + onComplete(image); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void Image_getBytesRenderThread(TLinearImage *tLinearImage, void (*onComplete)(float *)) + { + std::packaged_task lambda( + [=]() mutable + { + auto bytes = Image_getBytes(tLinearImage); + onComplete(bytes); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void Image_destroyRenderThread(TLinearImage *tLinearImage, void (*onComplete)()) + { + std::packaged_task lambda( + [=]() mutable + { + Image_destroy(tLinearImage); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void Image_getWidthRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t)) + { + std::packaged_task lambda( + [=]() mutable + { + auto width = Image_getWidth(tLinearImage); + onComplete(width); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void Image_getHeightRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t)) + { + std::packaged_task lambda( + [=]() mutable + { + auto height = Image_getHeight(tLinearImage); + onComplete(height); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void Image_getChannelsRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t)) + { + std::packaged_task lambda( + [=]() mutable + { + auto channels = Image_getChannels(tLinearImage); + onComplete(channels); + }); + auto fut = _rl->add_task(lambda); + } + + // Texture methods + EMSCRIPTEN_KEEPALIVE void Texture_loadImageRenderThread(TEngine *tEngine, TTexture *tTexture, TLinearImage *tImage, + TPixelDataFormat bufferFormat, TPixelDataType pixelDataType, + void (*onComplete)(bool)) + { + std::packaged_task lambda( + [=]() mutable + { + bool result = Texture_loadImage(tEngine, tTexture, tImage, bufferFormat, pixelDataType); + onComplete(result); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void Texture_setImageRenderThread( + TEngine *tEngine, + TTexture *tTexture, + uint32_t level, + uint8_t *data, + size_t size, + uint32_t width, + uint32_t height, + uint32_t channels, + uint32_t bufferFormat, + uint32_t pixelDataType, + void (*onComplete)(bool)) + { + std::packaged_task lambda( + [=]() mutable + { + bool result = Texture_setImage(tEngine, tTexture, level, data, size, width, height, channels, + bufferFormat, pixelDataType); + onComplete(result); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void RenderTarget_getColorTextureRenderThread(TRenderTarget *tRenderTarget, void (*onComplete)(TTexture *)) + { + std::packaged_task lambda( + [=]() mutable + { + auto texture = RenderTarget_getColorTexture(tRenderTarget); + onComplete(texture); + }); + auto fut = _rl->add_task(lambda); + } + + // TextureSampler methods + EMSCRIPTEN_KEEPALIVE void TextureSampler_createRenderThread(void (*onComplete)(TTextureSampler *)) + { + std::packaged_task lambda( + [=]() mutable + { + auto sampler = TextureSampler_create(); + onComplete(sampler); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithFilteringRenderThread( + TSamplerMinFilter minFilter, + TSamplerMagFilter magFilter, + TSamplerWrapMode wrapS, + TSamplerWrapMode wrapT, + TSamplerWrapMode wrapR, + void (*onComplete)(TTextureSampler *)) + { + std::packaged_task lambda( + [=]() mutable + { + auto sampler = TextureSampler_createWithFiltering(minFilter, magFilter, wrapS, wrapT, wrapR); + onComplete(sampler); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithComparisonRenderThread( + TSamplerCompareMode compareMode, + TSamplerCompareFunc compareFunc, + void (*onComplete)(TTextureSampler *)) + { + std::packaged_task lambda( + [=]() mutable + { + auto sampler = TextureSampler_createWithComparison(compareMode, compareFunc); + onComplete(sampler); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void TextureSampler_setMinFilterRenderThread( + TTextureSampler *sampler, + TSamplerMinFilter filter, + void (*onComplete)()) + { + std::packaged_task lambda( + [=]() mutable + { + TextureSampler_setMinFilter(sampler, filter); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void TextureSampler_setMagFilterRenderThread( + TTextureSampler *sampler, + TSamplerMagFilter filter, + void (*onComplete)()) + { + std::packaged_task lambda( + [=]() mutable + { + TextureSampler_setMagFilter(sampler, filter); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeSRenderThread( + TTextureSampler *sampler, + TSamplerWrapMode mode, + void (*onComplete)()) + { + std::packaged_task lambda( + [=]() mutable + { + TextureSampler_setWrapModeS(sampler, mode); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeTRenderThread( + TTextureSampler *sampler, + TSamplerWrapMode mode, + void (*onComplete)()) + { + std::packaged_task lambda( + [=]() mutable + { + TextureSampler_setWrapModeT(sampler, mode); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeRRenderThread( + TTextureSampler *sampler, + TSamplerWrapMode mode, + void (*onComplete)()) + { + std::packaged_task lambda( + [=]() mutable + { + TextureSampler_setWrapModeR(sampler, mode); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void TextureSampler_setAnisotropyRenderThread( + TTextureSampler *sampler, + double anisotropy, + void (*onComplete)()) + { + std::packaged_task lambda( + [=]() mutable + { + TextureSampler_setAnisotropy(sampler, anisotropy); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void TextureSampler_setCompareModeRenderThread( + TTextureSampler *sampler, + TSamplerCompareMode mode, + TTextureSamplerCompareFunc func, + void (*onComplete)()) + { + std::packaged_task lambda( + [=]() mutable + { + TextureSampler_setCompareMode(sampler, mode, func); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void TextureSampler_destroyRenderThread( + TTextureSampler *sampler, + void (*onComplete)()) + { + std::packaged_task lambda( + [=]() mutable + { + TextureSampler_destroy(sampler); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } }