use render thread methods for Texture/Image/TextureSampler

This commit is contained in:
Nick Fisher
2025-03-07 14:52:45 +08:00
parent 2915655695
commit 74ee35bfcd
7 changed files with 1025 additions and 85 deletions

View File

@@ -71,6 +71,21 @@ Future<int> withIntCallback(
return completer.future;
}
Future<int> withUInt32Callback(
Function(Pointer<NativeFunction<Void Function(Uint32)>>) func) async {
final completer = Completer<int>();
// ignore: prefer_function_declarations_over_variables
void Function(int) callback = (int result) {
completer.complete(result);
};
final nativeCallable =
NativeCallable<Void Function(Uint32)>.listener(callback);
func.call(nativeCallable.nativeFunction);
await completer.future;
nativeCallable.close();
return completer.future;
}
Future<String> withCharPtrCallback(
Function(Pointer<NativeFunction<Void Function(Pointer<Char>)>>)
func) async {

View File

@@ -9,26 +9,32 @@ class FFITexture extends Texture {
FFITexture(this._engine, this.pointer);
Future setLinearImage(covariant FFILinearImage image, PixelDataFormat format,
Future<void> 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<void> dispose() async {
await withVoidCallback((cb) {
Engine_destroyTextureRenderThread(_engine, pointer, cb);
});
}
@override
Future generateMipmaps() {
Future<void> generateMipmaps() {
// TODO: implement generateMipmaps
throw UnimplementedError();
}
@@ -70,15 +76,16 @@ class FFITexture extends Texture {
}
@override
Future setExternalImage(externalImage) {
Future<void> setExternalImage(externalImage) {
// TODO: implement setExternalImage
throw UnimplementedError();
}
@override
Future setImage(int level, Uint8List buffer, int width, int height,
Future<void> 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<void> 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<void> 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<FFILinearImage> createEmpty(int width, int height, int channels) async {
final imagePtr = await withPointerCallback<TLinearImage>((cb) {
Image_createEmptyRenderThread(width, height, channels, cb);
});
return FFILinearImage(imagePtr);
}
static Future<FFILinearImage> decode(Uint8List data, [String name = "image"]) async {
final namePtr = name.toNativeUtf8();
try {
final imagePtr = await withPointerCallback<TLinearImage>((cb) {
Image_decodeRenderThread(data.address, data.lengthInBytes, namePtr.cast(), cb);
});
return FFILinearImage(imagePtr);
} finally {
calloc.free(namePtr);
}
}
Future<void> destroy() async {
await withVoidCallback((cb) {
Image_destroyRenderThread(this.pointer, cb);
});
}
@override
Future<int> getChannels() async {
return Image_getChannels(pointer);
return await withUInt32Callback((cb) {
Image_getChannelsRenderThread(pointer, cb);
});
}
@override
Future<int> getHeight() async {
return Image_getHeight(pointer);
return await withUInt32Callback((cb) {
Image_getHeightRenderThread(pointer, cb);
});
}
@override
Future<int> 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<Float>((cb) {
Image_getBytesRenderThread(pointer, cb);
});
return ptr.asTypedList(height * width * channels);
}
}
// Add these to access TextureSampler functionality:
class FFITextureSampler extends TextureSampler {
final Pointer<TTextureSampler> pointer;
FFITextureSampler(this.pointer);
static Future<FFITextureSampler> create() async {
final samplerPtr = await withPointerCallback<TTextureSampler>((cb) {
TextureSampler_createRenderThread(cb);
});
return FFITextureSampler(samplerPtr);
}
// static Future<FFITextureSampler> createWithFiltering(
// SamplerMinFilter minFilter,
// SamplerMagFilter magFilter,
// SamplerWrapMode wrapS,
// SamplerWrapMode wrapT,
// SamplerWrapMode wrapR) async {
// final samplerPtr = await withPointerCallback<TTextureSampler>((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<FFITextureSampler> createWithComparison(
// SamplerCompareMode compareMode,
// SamplerCompareFunc compareFunc) async {
// final samplerPtr = await withPointerCallback<TTextureSampler>((cb) {
// TextureSampler_createWithComparisonRenderThread(
// TSamplerCompareMode.values[compareMode.index],
// TTextureSamplerCompareFunc.values[compareFunc.index],
// cb);
// });
// return FFITextureSampler(samplerPtr);
// }
// Future<void> setMinFilter(SamplerMinFilter filter) async {
// await withVoidCallback((cb) {
// TextureSampler_setMinFilterRenderThread(
// pointer,
// TSamplerMinFilter.values[filter.index],
// cb);
// });
// }
// Future<void> setMagFilter(SamplerMagFilter filter) async {
// await withVoidCallback((cb) {
// TextureSampler_setMagFilterRenderThread(
// pointer,
// TSamplerMagFilter.values[filter.index],
// cb);
// });
// }
// Future<void> setWrapModeS(SamplerWrapMode mode) async {
// await withVoidCallback((cb) {
// TextureSampler_setWrapModeSRenderThread(
// pointer,
// TSamplerWrapMode.values[mode.index],
// cb);
// });
// }
// Future<void> setWrapModeT(SamplerWrapMode mode) async {
// await withVoidCallback((cb) {
// TextureSampler_setWrapModeTRenderThread(
// pointer,
// TSamplerWrapMode.values[mode.index],
// cb);
// });
// }
// Future<void> setWrapModeR(SamplerWrapMode mode) async {
// await withVoidCallback((cb) {
// TextureSampler_setWrapModeRRenderThread(
// pointer,
// TSamplerWrapMode.values[mode.index],
// cb);
// });
// }
Future<void> setAnisotropy(double anisotropy) async {
await withVoidCallback((cb) {
TextureSampler_setAnisotropyRenderThread(pointer, anisotropy, cb);
});
}
// Future<void> 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);
});
}
}

View File

@@ -663,14 +663,6 @@ external void get_bounding_box_to_out(
ffi.Pointer<ffi.Float> maxY,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>, ffi.Pointer<ffi.Void>)>(isLeaf: true)
external void destroy_texture(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<ffi.Void> texture,
);
@ffi.Native<TViewport Function(ffi.Pointer<TView>)>(isLeaf: true)
external TViewport View_getViewport(
ffi.Pointer<TView> view,
@@ -1657,6 +1649,15 @@ void Engine_buildTextureRenderThread(
onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TEngine>, ffi.Pointer<TTexture>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void Engine_destroyTextureRenderThread(
ffi.Pointer<TEngine> engine,
ffi.Pointer<TTexture> tTexture,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TMaterial>,
@@ -2101,6 +2102,392 @@ external void AnimationManager_setMorphTargetWeightsRenderThread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Uint32,
ffi.Uint32,
ffi.Uint32,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<TLinearImage>)>>)>(isLeaf: true)
external void Image_createEmptyRenderThread(
int width,
int height,
int channel,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TLinearImage>)>>
onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Pointer<ffi.Char>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<TLinearImage>)>>)>(isLeaf: true)
external void Image_decodeRenderThread(
ffi.Pointer<ffi.Uint8> data,
int length,
ffi.Pointer<ffi.Char> name,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TLinearImage>)>>
onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TLinearImage>,
ffi.Pointer<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Float>)>>)>(
isLeaf: true)
external void Image_getBytesRenderThread(
ffi.Pointer<TLinearImage> tLinearImage,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Float>)>>
onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TLinearImage>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void Image_destroyRenderThread(
ffi.Pointer<TLinearImage> tLinearImage,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TLinearImage>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Uint32)>>)>(
isLeaf: true)
external void Image_getWidthRenderThread(
ffi.Pointer<TLinearImage> tLinearImage,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Uint32)>> onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TLinearImage>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Uint32)>>)>(
isLeaf: true)
external void Image_getHeightRenderThread(
ffi.Pointer<TLinearImage> tLinearImage,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Uint32)>> onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TLinearImage>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Uint32)>>)>(
isLeaf: true)
external void Image_getChannelsRenderThread(
ffi.Pointer<TLinearImage> tLinearImage,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Uint32)>> onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TEngine>,
ffi.Pointer<TTexture>,
ffi.Pointer<TLinearImage>,
ffi.UnsignedInt,
ffi.UnsignedInt,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>>)>(
symbol: "Texture_loadImageRenderThread", isLeaf: true)
external void _Texture_loadImageRenderThread(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TTexture> tTexture,
ffi.Pointer<TLinearImage> tImage,
int bufferFormat,
int pixelDataType,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> onComplete,
);
void Texture_loadImageRenderThread(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TTexture> tTexture,
ffi.Pointer<TLinearImage> tImage,
TPixelDataFormat bufferFormat,
TPixelDataType pixelDataType,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> onComplete,
) =>
_Texture_loadImageRenderThread(
tEngine,
tTexture,
tImage,
bufferFormat.value,
pixelDataType.value,
onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TEngine>,
ffi.Pointer<TTexture>,
ffi.Uint32,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Uint32,
ffi.Uint32,
ffi.Uint32,
ffi.Uint32,
ffi.Uint32,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>>)>(
isLeaf: true)
external void Texture_setImageRenderThread(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TTexture> tTexture,
int level,
ffi.Pointer<ffi.Uint8> data,
int size,
int width,
int height,
int channels,
int bufferFormat,
int pixelDataType,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TRenderTarget>,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TTexture>)>>)>(
isLeaf: true)
external void RenderTarget_getColorTextureRenderThread(
ffi.Pointer<TRenderTarget> tRenderTarget,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TTexture>)>>
onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<TTextureSampler>)>>)>(isLeaf: true)
external void TextureSampler_createRenderThread(
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TTextureSampler>)>>
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<TTextureSampler>)>>)>(
symbol: "TextureSampler_createWithFilteringRenderThread", isLeaf: true)
external void _TextureSampler_createWithFilteringRenderThread(
int minFilter,
int magFilter,
int wrapS,
int wrapT,
int wrapR,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TTextureSampler>)>>
onComplete,
);
void TextureSampler_createWithFilteringRenderThread(
TSamplerMinFilter minFilter,
TSamplerMagFilter magFilter,
TSamplerWrapMode wrapS,
TSamplerWrapMode wrapT,
TSamplerWrapMode wrapR,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TTextureSampler>)>>
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<TTextureSampler>)>>)>(
symbol: "TextureSampler_createWithComparisonRenderThread", isLeaf: true)
external void _TextureSampler_createWithComparisonRenderThread(
int compareMode,
int compareFunc,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TTextureSampler>)>>
onComplete,
);
void TextureSampler_createWithComparisonRenderThread(
TSamplerCompareMode compareMode,
TSamplerCompareFunc compareFunc,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TTextureSampler>)>>
onComplete,
) =>
_TextureSampler_createWithComparisonRenderThread(
compareMode.value,
compareFunc.value,
onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TTextureSampler>, ffi.UnsignedInt,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: "TextureSampler_setMinFilterRenderThread", isLeaf: true)
external void _TextureSampler_setMinFilterRenderThread(
ffi.Pointer<TTextureSampler> sampler,
int filter,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
void TextureSampler_setMinFilterRenderThread(
ffi.Pointer<TTextureSampler> sampler,
TSamplerMinFilter filter,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
) =>
_TextureSampler_setMinFilterRenderThread(
sampler,
filter.value,
onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TTextureSampler>, ffi.UnsignedInt,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: "TextureSampler_setMagFilterRenderThread", isLeaf: true)
external void _TextureSampler_setMagFilterRenderThread(
ffi.Pointer<TTextureSampler> sampler,
int filter,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
void TextureSampler_setMagFilterRenderThread(
ffi.Pointer<TTextureSampler> sampler,
TSamplerMagFilter filter,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
) =>
_TextureSampler_setMagFilterRenderThread(
sampler,
filter.value,
onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TTextureSampler>, ffi.UnsignedInt,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: "TextureSampler_setWrapModeSRenderThread", isLeaf: true)
external void _TextureSampler_setWrapModeSRenderThread(
ffi.Pointer<TTextureSampler> sampler,
int mode,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
void TextureSampler_setWrapModeSRenderThread(
ffi.Pointer<TTextureSampler> sampler,
TSamplerWrapMode mode,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
) =>
_TextureSampler_setWrapModeSRenderThread(
sampler,
mode.value,
onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TTextureSampler>, ffi.UnsignedInt,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: "TextureSampler_setWrapModeTRenderThread", isLeaf: true)
external void _TextureSampler_setWrapModeTRenderThread(
ffi.Pointer<TTextureSampler> sampler,
int mode,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
void TextureSampler_setWrapModeTRenderThread(
ffi.Pointer<TTextureSampler> sampler,
TSamplerWrapMode mode,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
) =>
_TextureSampler_setWrapModeTRenderThread(
sampler,
mode.value,
onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TTextureSampler>, ffi.UnsignedInt,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: "TextureSampler_setWrapModeRRenderThread", isLeaf: true)
external void _TextureSampler_setWrapModeRRenderThread(
ffi.Pointer<TTextureSampler> sampler,
int mode,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
void TextureSampler_setWrapModeRRenderThread(
ffi.Pointer<TTextureSampler> sampler,
TSamplerWrapMode mode,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
) =>
_TextureSampler_setWrapModeRRenderThread(
sampler,
mode.value,
onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TTextureSampler>, ffi.Double,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void TextureSampler_setAnisotropyRenderThread(
ffi.Pointer<TTextureSampler> sampler,
double anisotropy,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TTextureSampler>,
ffi.UnsignedInt,
ffi.UnsignedInt,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: "TextureSampler_setCompareModeRenderThread", isLeaf: true)
external void _TextureSampler_setCompareModeRenderThread(
ffi.Pointer<TTextureSampler> sampler,
int mode,
int func,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
void TextureSampler_setCompareModeRenderThread(
ffi.Pointer<TTextureSampler> sampler,
TSamplerCompareMode mode,
TSamplerCompareFunc func,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
) =>
_TextureSampler_setCompareModeRenderThread(
sampler,
mode.value,
func.value,
onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TTextureSampler>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void TextureSampler_destroyRenderThread(
ffi.Pointer<TTextureSampler> sampler,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>>)>(

View File

@@ -426,10 +426,3 @@ abstract class LinearImage {
Future<int> getChannels();
}
class FFITextureSampler extends TextureSampler {
final Pointer<TTextureSampler> pointer;
FFITextureSampler(this.pointer);
@override
Future dispose() async {}
}