STBImage.stbi_loadf to return a ByteBuffer instead of a FloatBuffer

Started by arisona, April 12, 2016, 14:29:53

Previous topic - Next topic

arisona

STBImage.stbi_loadf currently returns a FloatBuffer, which needs to be freed with STBImage.stbi_image_free, taking a ByteBuffer as argument. AFAIK, it's easy to get a FloatBuffer from a ByteBuffer, but not vice versa (a workaround would probably be MemoryUtil).

Wouldn't it be preferable if STBImage.stbi_loadf just returned a ByteBuffer, from where handling as FloatBuffer and freeing would be straightforward?

Cheers, /Stefan

spasi

Thanks, the next nightly build will include stbi_image_free(FloatBuffer).

arisona

Cool - this will work for me too.

(My reason for preferring stbi_loadf to return a ByteBuffer is that I have a generic image reader, which wraps byte and float images into an image class, together with data type, and internally only uses a ByteBuffer. But probably too much of a special case, so stbi_image_free(FloatBuffer) is fine.)  :)

Thanks!

arisona

There's one more detail regarding STBImage.stbi_image_free():

The buffer needs to be reset, otherwise free() attempts to free the wrong address.

I understand this is due to how internally addresses are dealt with, but I wonder if there's no better solution for such cases, since one always (?) wants to free a buffer's base address.

spasi

I could add special support for such cases in the code generator. JEmalloc.free and Stdlib.free could also use it. On the other hand, all LWJGL methods have the same contract: when you pass a buffer argument, you tell LWJGL to do something with the memory address at the current buffer position. So, having to reset the position is not an unusual requirement.

I'll propose two workarounds, let me know if either is good enough for you:

- You can use the unsafe version like so: nstbi_image_free(memAddress0(imageBuffer))

The memAddress0 in MemoryUtil returns the base buffer address, ignoring the current position. It is equivalent to JNI's GetDirectBufferAddress.

- You can simply use the default allocator via MemoryUtil: memFree(imageBuffer)

This is an implementation detail, but it is guaranteed that stb uses the same allocator as LWJGL's explicit memory management API. The same is true for any other library that comes with LWJGL and has configurable allocation. The allocator can be changed with the Configuration.MEMORY_ALLOCATOR option and defaults to jemalloc. So, calling stbi_image_free is basically the same as calling memFree (which by default is the same as calling JEmalloc.free).

The memFree and memAlignedFree methods are the only methods in LWJGL that "break" the buffer contract and use memAddress0 internally, so they already do the right thing.

arisona

Ok, I see. I think your statement on the general contract "when you pass a buffer argument, you tell LWJGL to do something with the memory address at the current buffer position" is enough - one just needs to be aware of this, and then resetting before calling free will be obvious.