LWJGL Forum

Please login or register.

Login with username, password and session length

Author Topic: Is it possible to gain more control over ByteBuffers returned by STBImage?  (Read 139 times)

ILikeCubes

  • Newbie
  • *
  • Offline Offline
  • Posts: 3

The ByteBuffer returned by stbi_load_from_memory seems to be managed by the garbage collector (allocated with allocateDirect()?). The issue is, that I would really like to have more control over when to free this buffer since large uncompressed textures can take up a lot of space.
I thought about just copying the buffer into a new one that is manually managed by my app, but this would mean to eat the overhead of allocating a new buffer and copying into it, in addition to still not having much control over when the original allocation would be freed.
Another possibility seems to be to use reflection to free the direct buffer manually but I am not sure if this is really a good path to take.
Would it be possible to modify the stbi_load_from_memory function to pass in your own allocation?

I hope I am not missing something obvious and thanks in advance for any insight!
Logged

spasi

  • Administrator
  • Nerdus Imperius
  • *****
  • Offline Offline
  • Posts: 1837

The ByteBuffer returned by stbi_load_from_memory simply wraps the pointer returned by the native function. ByteBuffer.allocateDirect is not called, any allocation happens internally in stb_image. You can (and should) free the image explicitly using stbi_image_free.

Advanced info: stb_image and a few other bindings can be configured with custom memory allocations functions, at build time usually. LWJGL takes advantage of that and configures everything to use the same allocator as the one used by MemoryUtil (which is configurable at runtime). This means that, effectively, stbi_image_free is equivalent to MemoryUtil.memFree.
Logged

ILikeCubes

  • Newbie
  • *
  • Offline Offline
  • Posts: 3

Thanks for the explanation, I should have looked closer at the example!

This is probably related to my (lack of) understanding of memory management and not very lwjgl specific, but what I don't understand is this:
If both allocations are made with the same allocator(debug) and in the same process, why do the stbi allocations not show up in the memReport() callback and why can they not be freed with a call to memFree()? If I have a ByteBuffer object should I not have enough information(the pointer) to free the native memory? Is it a matter of scope/visibility?
Logged

spasi

  • Administrator
  • Nerdus Imperius
  • *****
  • Offline Offline
  • Posts: 1837

why do the stbi allocations not show up in the memReport() callback

The allocation does not show up in memReport because stb_image uses the native allocator directly. The debug allocator wraps the native allocator and only tracks allocations made via the MemoryUtil API.

why can they not be freed with a call to memFree()? If I have a ByteBuffer object should I not have enough information(the pointer) to free the native memory? Is it a matter of scope/visibility?

The memFree would work without the debug allocator. But it's not recommended that you do that, when a dedicated stbi_image_free exists. This one doesn't, but such functions might do other important cleanup, besides calling the native allocator free.
Logged

ILikeCubes

  • Newbie
  • *
  • Offline Offline
  • Posts: 3

That makes a lot of sense, thanks for your help!
Logged