diff --git a/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart b/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart index 7fbd51dd..ae8360cd 100644 --- a/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart +++ b/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart @@ -636,30 +636,6 @@ external bool Texture_loadImage( int level, ); -@ffi.Native< - ffi.Bool Function( - ffi.Pointer, - ffi.Pointer, - ffi.Uint32, - ffi.Pointer, - ffi.Size, - ffi.Uint32, - ffi.Uint32, - ffi.Uint32, - ffi.Uint32, - ffi.Uint32)>(isLeaf: true) -external bool Texture_setImage( - ffi.Pointer tEngine, - ffi.Pointer tTexture, - int level, - ffi.Pointer data, - int size, - int width, - int height, - int channels, - int bufferFormat, - int pixelDataType, -); @ffi.Native< ffi.Bool Function( @@ -677,7 +653,7 @@ external bool Texture_setImage( ffi.Uint32, ffi.Uint32, ffi.Uint32)>(isLeaf: true) -external bool Texture_setImageWithDepth( +external bool Texture_setImage( ffi.Pointer tEngine, ffi.Pointer tTexture, int level, @@ -2531,33 +2507,6 @@ external void Texture_loadImageRenderThread( ffi.Pointer> 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( @@ -2574,10 +2523,9 @@ external void Texture_setImageRenderThread( ffi.Uint32, ffi.Uint32, ffi.Uint32, - ffi.Uint32, ffi.Pointer>)>( isLeaf: true) -external void Texture_setImageWithDepthRenderThread( +external void Texture_setImageRenderThread( ffi.Pointer tEngine, ffi.Pointer tTexture, int level, @@ -2588,7 +2536,6 @@ external void Texture_setImageWithDepthRenderThread( int z_offset, int width, int height, - int channels, int depth, int bufferFormat, int pixelDataType, diff --git a/thermion_dart/lib/src/bindings/src/thermion_dart_js_interop.g.dart b/thermion_dart/lib/src/bindings/src/thermion_dart_js_interop.g.dart index 7c2d4043..d2374807 100644 --- a/thermion_dart/lib/src/bindings/src/thermion_dart_js_interop.g.dart +++ b/thermion_dart/lib/src/bindings/src/thermion_dart_js_interop.g.dart @@ -752,19 +752,8 @@ extension type NativeLibrary(JSObject _) implements JSObject { int pixelDataType, int level, ); + external int _Texture_setImage( - Pointer tEngine, - Pointer tTexture, - int level, - Pointer data, - size_t size, - int width, - int height, - int channels, - int bufferFormat, - int pixelDataType, - ); - external int _Texture_setImageWithDepth( Pointer tEngine, Pointer tTexture, int level, @@ -775,7 +764,6 @@ extension type NativeLibrary(JSObject _) implements JSObject { int z_offset, int width, int height, - int channels, int depth, int bufferFormat, int pixelDataType, @@ -1748,19 +1736,6 @@ extension type NativeLibrary(JSObject _) implements JSObject { Pointer> onComplete, ); external void _Texture_setImageRenderThread( - Pointer tEngine, - Pointer tTexture, - int level, - Pointer data, - size_t size, - int width, - int height, - int channels, - int bufferFormat, - int pixelDataType, - Pointer> onComplete, - ); - external void _Texture_setImageWithDepthRenderThread( Pointer tEngine, Pointer tTexture, int level, @@ -1771,7 +1746,6 @@ extension type NativeLibrary(JSObject _) implements JSObject { int z_offset, int width, int height, - int channels, int depth, int bufferFormat, int pixelDataType, @@ -3024,23 +2998,6 @@ bool Texture_loadImage( } bool Texture_setImage( - self.Pointer tEngine, - self.Pointer tTexture, - int level, - self.Pointer data, - Dart__darwin_size_t size, - int width, - int height, - int channels, - int bufferFormat, - int pixelDataType, -) { - final result = _lib._Texture_setImage(tEngine.cast(), tTexture.cast(), level, - data, size, width, height, channels, bufferFormat, pixelDataType); - return result == 1; -} - -bool Texture_setImageWithDepth( self.Pointer tEngine, self.Pointer tTexture, int level, @@ -3051,12 +3008,11 @@ bool Texture_setImageWithDepth( int z_offset, int width, int height, - int channels, int depth, int bufferFormat, int pixelDataType, ) { - final result = _lib._Texture_setImageWithDepth( + final result = _lib._Texture_setImage( tEngine.cast(), tTexture.cast(), level, @@ -3067,7 +3023,6 @@ bool Texture_setImageWithDepth( z_offset, width, height, - channels, depth, bufferFormat, pixelDataType); @@ -5083,46 +5038,17 @@ void Texture_setImageRenderThread( int level, self.Pointer data, Dart__darwin_size_t size, + int x_offset, + int y_offset, + int z_offset, int width, int height, - int channels, + int depth, int bufferFormat, int pixelDataType, self.Pointer> onComplete, ) { final result = _lib._Texture_setImageRenderThread( - tEngine.cast(), - tTexture.cast(), - level, - data, - size, - width, - height, - channels, - bufferFormat, - pixelDataType, - onComplete.cast()); - return result; -} - -void Texture_setImageWithDepthRenderThread( - self.Pointer tEngine, - self.Pointer tTexture, - int level, - self.Pointer data, - Dart__darwin_size_t size, - int x_offset, - int y_offset, - int z_offset, - int width, - int height, - int channels, - int depth, - int bufferFormat, - int pixelDataType, - self.Pointer> onComplete, -) { - final result = _lib._Texture_setImageWithDepthRenderThread( tEngine.cast(), tTexture.cast(), level, @@ -5133,7 +5059,6 @@ void Texture_setImageWithDepthRenderThread( z_offset, width, height, - channels, depth, bufferFormat, pixelDataType, diff --git a/thermion_dart/lib/src/filament/src/implementation/ffi_texture.dart b/thermion_dart/lib/src/filament/src/implementation/ffi_texture.dart index 3d22e405..a491268b 100644 --- a/thermion_dart/lib/src/filament/src/implementation/ffi_texture.dart +++ b/thermion_dart/lib/src/filament/src/implementation/ffi_texture.dart @@ -30,7 +30,8 @@ class FFITexture extends Texture { @override Future generateMipmaps() async { - await withVoidCallback((requestId, cb) => Texture_generateMipMapsRenderThread(pointer, _engine, requestId, cb)); + await withVoidCallback((requestId, cb) => + Texture_generateMipMapsRenderThread(pointer, _engine, requestId, cb)); } @override @@ -73,7 +74,8 @@ class FFITexture extends Texture { @override Future setImage(int level, Uint8List buffer, int width, int height, - int channels, PixelDataFormat format, PixelDataType type) async { + PixelDataFormat format, PixelDataType type, + {int depth = 1, int xOffset = 0, int yOffset = 0, int zOffset = 0 }) async { final success = await withBoolCallback((cb) { Texture_setImageRenderThread( _engine, @@ -81,9 +83,10 @@ class FFITexture extends Texture { level, buffer.address, buffer.lengthInBytes, + xOffset, yOffset, zOffset, width, height, - channels, + depth, format.index, type.index, cb); @@ -94,44 +97,6 @@ class FFITexture extends Texture { } } - @override - Future setImage3D( - int level, - int xOffset, - int yOffset, - int zOffset, - int width, - int height, - int channels, - int depth, - Uint8List buffer, - PixelDataFormat format, - PixelDataType type) async { - throw UnimplementedError(); - // final success = await withBoolCallback((cb) { - // Texture_setImageWithDepthRenderThread( - // _engine, - // pointer, - // level, - // buffer.address, - // buffer.lengthInBytes, - // 0, - // 0, - // zOffset, - // width, - // height, - // channels, - // depth, - // format.index, - // type.index, - // cb); - // }); - - // if (!success) { - // throw Exception("Failed to set image"); - // } - } - @override Future setSubImage( int level, diff --git a/thermion_dart/lib/src/filament/src/interface/texture.dart b/thermion_dart/lib/src/filament/src/interface/texture.dart index f37f7658..0d860be2 100644 --- a/thermion_dart/lib/src/filament/src/interface/texture.dart +++ b/thermion_dart/lib/src/filament/src/interface/texture.dart @@ -333,30 +333,18 @@ abstract class Texture { /// Sets the given [image] as the source data for this texture. /// Future setLinearImage( - covariant LinearImage image, PixelDataFormat format, PixelDataType type, {int level = 0}); + covariant LinearImage image, PixelDataFormat format, PixelDataType type, + {int level = 0}); /// Sets the image data for a 2D texture or a texture level - Future setImage(int level, Uint8List buffer, int width, int height, - int channels, PixelDataFormat format, PixelDataType type); + Future setImage(int level, Uint8List buffer, int width, int height, + PixelDataFormat format, PixelDataType type, + {int depth = 1, int xOffset = 0, int yOffset = 0, int zOffset = 0}); /// Sets the image data for a region of a 2D texture Future setSubImage(int level, int xOffset, int yOffset, int width, int height, Uint8List buffer, PixelDataFormat format, PixelDataType type); - /// Sets the image data for a 3D texture or cubemap - Future setImage3D( - int level, - int xOffset, - int yOffset, - int zOffset, - int width, - int height, - int channels, - int depth, - Uint8List buffer, - PixelDataFormat format, - PixelDataType type); - /// Sets an external image (like a video or camera frame) as the texture source Future setExternalImage(dynamic externalImage); @@ -407,15 +395,16 @@ enum PixelDataFormat { /// The integer value of the enum final int value; - + /// Constructor with the integer value const PixelDataFormat(this.value); - + /// Factory constructor to create a PixelDataFormat from an integer value factory PixelDataFormat.fromValue(int value) { return PixelDataFormat.values.firstWhere( (format) => format.value == value, - orElse: () => throw ArgumentError('Invalid PixelDataFormat value: $value'), + orElse: () => + throw ArgumentError('Invalid PixelDataFormat value: $value'), ); } } @@ -460,10 +449,10 @@ enum PixelDataType { /// The integer value of the enum final int value; - + /// Constructor with the integer value const PixelDataType(this.value); - + /// Factory constructor to create a PixelDataType from an integer value factory PixelDataType.fromValue(int value) { return PixelDataType.values.firstWhere( @@ -473,7 +462,6 @@ enum PixelDataType { } } - @deprecated typedef ThermionTexture = Texture; @@ -483,34 +471,26 @@ abstract class LinearImage { Future getWidth(); Future getHeight(); Future getChannels(); - - /// Decodes the image contained in [data] and returns a texture of - /// the corresponding size with the image set as mip-level 0. - /// - /// - static Future decodeToTexture(Uint8List data, { - TextureFormat textureFormat = TextureFormat.RGB32F, - PixelDataFormat pixelDataFormat = PixelDataFormat.RGB, - PixelDataType pixelDataType = PixelDataType.FLOAT, - int levels = 1, - bool requireAlpha = false}) async { - final decodedImage = await FilamentApp.instance!.decodeImage(data, requireAlpha: requireAlpha); - - final texture = await FilamentApp.instance!.createTexture( - await decodedImage.getWidth(), - await decodedImage.getHeight(), - textureFormat: textureFormat, - levels:levels - ); - await texture.setLinearImage( - decodedImage, - pixelDataFormat, - pixelDataType - ); + /// Decodes the image contained in [data] and returns a texture of + /// the corresponding size with the image set as mip-level 0. + /// + /// + static Future decodeToTexture(Uint8List data, + {TextureFormat textureFormat = TextureFormat.RGB32F, + PixelDataFormat pixelDataFormat = PixelDataFormat.RGB, + PixelDataType pixelDataType = PixelDataType.FLOAT, + int levels = 1, + bool requireAlpha = false}) async { + final decodedImage = await FilamentApp.instance! + .decodeImage(data, requireAlpha: requireAlpha); + + final texture = await FilamentApp.instance!.createTexture( + await decodedImage.getWidth(), await decodedImage.getHeight(), + textureFormat: textureFormat, levels: levels); + + await texture.setLinearImage(decodedImage, pixelDataFormat, pixelDataType); return texture; } - } - diff --git a/thermion_dart/native/include/c_api/TTexture.h b/thermion_dart/native/include/c_api/TTexture.h index b088dd9b..fce14c4c 100644 --- a/thermion_dart/native/include/c_api/TTexture.h +++ b/thermion_dart/native/include/c_api/TTexture.h @@ -228,18 +228,6 @@ EMSCRIPTEN_KEEPALIVE bool Texture_loadImage( int level ); EMSCRIPTEN_KEEPALIVE bool Texture_setImage( - 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 -); -EMSCRIPTEN_KEEPALIVE bool Texture_setImageWithDepth( TEngine *tEngine, TTexture *tTexture, uint32_t level, @@ -250,7 +238,6 @@ EMSCRIPTEN_KEEPALIVE bool Texture_setImageWithDepth( uint32_t z_offset, uint32_t width, uint32_t height, - uint32_t channels, uint32_t depth, uint32_t bufferFormat, uint32_t pixelDataType diff --git a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h index 22003e90..7148d9cd 100644 --- a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h +++ b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h @@ -194,19 +194,6 @@ namespace thermion void (*onComplete)(bool) ); 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) - ); - void Texture_setImageWithDepthRenderThread( TEngine *tEngine, TTexture *tTexture, uint32_t level, @@ -217,7 +204,6 @@ namespace thermion uint32_t z_offset, uint32_t width, uint32_t height, - uint32_t channels, uint32_t depth, uint32_t bufferFormat, uint32_t pixelDataType, diff --git a/thermion_dart/native/src/c_api/TTexture.cpp b/thermion_dart/native/src/c_api/TTexture.cpp index 7a5a69ff..57d5d1e9 100644 --- a/thermion_dart/native/src/c_api/TTexture.cpp +++ b/thermion_dart/native/src/c_api/TTexture.cpp @@ -532,62 +532,6 @@ namespace thermion } EMSCRIPTEN_KEEPALIVE bool Texture_setImage( - TEngine *tEngine, - TTexture *tTexture, - uint32_t level, - uint8_t *data, - size_t size, - uint32_t width, - uint32_t height, - uint32_t channels, - uint32_t tBufferFormat, - uint32_t tPixelDataType) - { - auto engine = reinterpret_cast(tEngine); - - auto texture = reinterpret_cast(tTexture); - auto bufferFormat = static_cast(tBufferFormat); - auto pixelDataType = static_cast(tPixelDataType); - - switch (bufferFormat) - { - case PixelBufferDescriptor::PixelDataFormat::RGB: - case PixelBufferDescriptor::PixelDataFormat::RGBA: - case PixelBufferDescriptor::PixelDataFormat::RGB_INTEGER: - case PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER: - break; - default: - Log("Unsupported buffer format type : %d", bufferFormat); - return false; - } - - // the texture upload is async, so we need to copy the buffer - auto *buffer = new std::vector(size); - std::copy(data, data + size, buffer->begin()); - - filament::Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t, - void *data) - { - delete reinterpret_cast *>(data); - }; - - filament::Texture::PixelBufferDescriptor pbd( - buffer->data(), - size, - bufferFormat, - pixelDataType, - 1, // alignment - 0, // left - 0, // top - 0, // stride - freeCallback, - buffer); - - texture->setImage(*engine, level, std::move(pbd)); - return true; - } - - EMSCRIPTEN_KEEPALIVE bool Texture_setImageWithDepth( TEngine *tEngine, TTexture *tTexture, uint32_t level, @@ -598,7 +542,6 @@ namespace thermion uint32_t z_offset, uint32_t width, uint32_t height, - uint32_t channels, uint32_t depth, uint32_t tBufferFormat, uint32_t tPixelDataType) @@ -608,34 +551,18 @@ namespace thermion auto texture = reinterpret_cast(tTexture); auto bufferFormat = static_cast(tBufferFormat); auto pixelDataType = static_cast(tPixelDataType); - TRACE("Setting texture image (depth %d, %dx%dx%d (%d bytes, z_offset %d)", depth, width, height, channels, size, z_offset); + TRACE("Setting texture image for level %d, offset %dx%dx%d, depth %d", level, x_offset, y_offset, z_offset, depth); switch (bufferFormat) { - case PixelBufferDescriptor::PixelDataFormat::RGB: - case PixelBufferDescriptor::PixelDataFormat::RGBA: - { - size_t expectedSize = width * height * channels * sizeof(float); - if (size != expectedSize) - { - Log("Size mismatch (expected %lu, got %lu)", expectedSize, size); + case PixelBufferDescriptor::PixelDataFormat::RGB: + case PixelBufferDescriptor::PixelDataFormat::RGBA: + case PixelBufferDescriptor::PixelDataFormat::RGB_INTEGER: + case PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER: + break; + default: + Log("Unsupported buffer format type : %d", bufferFormat); return false; - } - break; - } - case PixelBufferDescriptor::PixelDataFormat::RGB_INTEGER: - case PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER: - { - if (size != width * height * channels * sizeof(uint8_t)) - { - Log("Size mismatch"); - // return false; - } - break; - } - default: - Log("Unsupported buffer format type : %d", bufferFormat); - return false; } // the texture upload is async, so we need to copy the buffer diff --git a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp index 58ca6180..9da96059 100644 --- a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp +++ b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp @@ -937,29 +937,6 @@ extern "C" } 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); - PROXY(onComplete(result)); - }); - auto fut = _renderThread->add_task(lambda); - } - - EMSCRIPTEN_KEEPALIVE void Texture_setImageWithDepthRenderThread( TEngine *tEngine, TTexture *tTexture, uint32_t level, @@ -970,7 +947,6 @@ extern "C" uint32_t z_offset, uint32_t width, uint32_t height, - uint32_t channels, uint32_t depth, uint32_t bufferFormat, uint32_t pixelDataType, @@ -979,7 +955,7 @@ extern "C" std::packaged_task lambda( [=]() mutable { - bool result = Texture_setImageWithDepth( + bool result = Texture_setImage( tEngine, tTexture, level, @@ -990,7 +966,6 @@ extern "C" z_offset, width, height, - channels, depth, bufferFormat, pixelDataType); diff --git a/thermion_dart/test/texture_tests.dart b/thermion_dart/test/texture_tests.dart index d2d825e6..07a36276 100644 --- a/thermion_dart/test/texture_tests.dart +++ b/thermion_dart/test/texture_tests.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'package:image/image.dart'; import 'package:test/test.dart'; import 'package:thermion_dart/thermion_dart.dart'; import 'helpers.dart'; @@ -8,12 +9,13 @@ void main() async { await testHelper.setup(); group("image", () { - test('create 2D texture & set from decoded image', () async { + test('set 2D texture from decoded image', () async { await testHelper.withViewer((viewer) async { var imageData = File( "${testHelper.testDir}/assets/cube_texture_512x512.png", ).readAsBytesSync(); - final image = await FilamentApp.instance!.decodeImage(imageData); + final image = await FilamentApp.instance! + .decodeImage(imageData, requireAlpha: true); expect(await image.getChannels(), 4); expect(await image.getWidth(), 512); expect(await image.getHeight(), 512); @@ -32,6 +34,36 @@ void main() async { }, bg: kRed); }); + test('set cubemap texture from pixel buffer', () async { + await testHelper.withViewer((viewer) async { + final texture = await FilamentApp.instance!.createTexture( + 1, + 1, + depth: 6, + textureSamplerType: TextureSamplerType.SAMPLER_CUBEMAP, + textureFormat: TextureFormat.RGBA32F, + ); + final byteBuffer = Float32List.fromList([ + 1.0, + 1.0, + 1.0, + 1.0, + ]); + for (int i = 0; i < 6; i++) { + await texture.setImage( + 0, + byteBuffer.asUint8List(), + 1, + 1, + zOffset: i, + PixelDataFormat.RGBA, + PixelDataType.FLOAT, + ); + } + await texture.dispose(); + }, bg: kRed); + }); + test('generate mipmaps', () async { await testHelper.withViewer((viewer) async { var imageData = File( @@ -49,7 +81,8 @@ void main() async { var imageData = File( "${testHelper.testDir}/assets/cube_texture_512x512.png", ).readAsBytesSync(); - final image = await FilamentApp.instance!.decodeImage(imageData); + final image = await FilamentApp.instance! + .decodeImage(imageData, requireAlpha: true); expect(await image.getChannels(), 4); expect(await image.getWidth(), 512); expect(await image.getHeight(), 512); @@ -66,7 +99,6 @@ void main() async { data.buffer.asUint8List(data.offsetInBytes), 512, 512, - 4, PixelDataFormat.RGBA, PixelDataType.FLOAT, ); @@ -90,18 +122,14 @@ void main() async { for (int i = 0; i < depth; i++) { final buffer = Uint8List(width * height * channels * sizeOf()); - await texture.setImage3D( + await texture.setImage( 0, - 0, - 0, - i, + buffer, width, height, - channels, - 1, - buffer, PixelDataFormat.RGBA, PixelDataType.FLOAT, + zOffset: i, ); } await texture.dispose(); @@ -145,18 +173,14 @@ void main() async { pixelBuffer.offsetInBytes, ); - await texture.setImage3D( + await texture.setImage( 0, - 0, - 0, - i, + byteBuffer, width, height, - channels, - 1, - byteBuffer, PixelDataFormat.RGBA, PixelDataType.FLOAT, + zOffset: i, ); }