Changing pixels in a Texture or Image via GDNative

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Hartmut Seichter

I am working on integrating my SSTT AR tracking engine into Godot for later release as free plugin. However I need to pick the brain of the community regarding texture upload from an external image.

I tried pulling and pushing textures / images. Here are the two methods I tried:

Method One: in GDNative I created a godot_pool_byte_array to keep the image data, hand this over with a variant and set it in an image which is attached to a Texture. It works but it leaks like crazy because set_image (in ImageTexture) or set_data (in Image) seem to create a new image every call. One can see this in the remote debugger as on every call a new instance of an image is being attached to the ImageTexture.

Method Two: in GDNative I have a function where I planned to copy the image data (capture data) into the byte buffer. The copy is done (I check the pointer its always the same). But again here the texture is not being update. I fenced the write to the GDScript handed in PoolByteArray into a godot_pool_byte_array_write_access which returns a nullpointer on godot_pool_byte_array_write_access_ptr. So no luck with this path either.

So, any other possibilities?

Assigning new data to an Image should not create an additional image, there is probably a bug there…
Also when you say “leak”, you mean memory goes up until starved?

Zylann | 2018-03-26 12:44

ImageTexture is creating a new Image every time a new (even the same) PoolByteArray is being set to the attached Image. This does not leak - I didn’t have a deeper look with valgrind.

What leaks is when you are using get_data() on the Image try to hand it over to a conversion (in my case a camera capture module) method and try to set it back. As reduz pointed out the API design is taking a immutable approach on the PoolXArray stuff.

I think there needs to be much more documentation around those kind of things. I only figured it out by trial and error, well and reading bug reports.

Hartmut Seichter | 2018-03-27 08:52

:bust_in_silhouette: Reply From: Hartmut Seichter

For reference as other people will likely try to do some GDNative stuff, here is my approach:

Within GDNative module I am keeping a PoolByteArray instance. If I get the first frame I instantiate a new PoolByteArray with
api->godot_pool_byte_array_new(&user_data->pba); api->godot_pool_byte_array_resize(&user_data->pba,img_size);
if the user changes camera settings or the you need to destroy the image and re-instantiate.

to use the data just get a variant with the PoolByteArray

api->godot_variant_new_pool_byte_array(&ret,&user_data->pba);

on the GDScript part this translates to

 var data = gdni.get_data()
	
nodeImage.data.data = data
	
nodeImageTexture.set_data(nodeImage)

Hope this clears up some of the confusion.