Barbo24
Barbo24

Reputation: 49

two identical ByteBuffers behaving differently

I have two ByteBuffers, they are completely identical but somehow behave differently when used in the GL11.glTexImage2D(); method.

My code:

IntBuffer width = BufferUtils.createIntBuffer(1);
IntBuffer height = BufferUtils.createIntBuffer(1);
IntBuffer comp = BufferUtils.createIntBuffer(1);

ByteBuffer data = STBImage.stbi_load("dsc8x12.bmp", width, height, comp, 4);

byte[] bytes = new byte[data.limit()];
for (int i = 0; i < bytes.length; i++) {
    bytes[i] = data.get(i);
}
ByteBuffer data2 = ByteBuffer.wrap(bytes);

System.out.println(data.equals(data2));

GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 1024, 12, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, data);

The console output is true

Here is how the window looks when the final argument in the GL11.glTexImage2D(); is either data or data2

When data is used: when data is used

When data2 is used: when data2 is used

Upvotes: 2

Views: 166

Answers (1)

httpdigest
httpdigest

Reputation: 5806

The reason why you get two different results with the two different ByteBuffers is that LWJGL only works with direct NIO Buffers, that is, ByteBuffers that are not backed by arrays.

The reason for this particular output that you are getting is two-fold:

  1. the non-direct ByteBuffer you supply (the one being created by .wrap(array)) has an internal address field value of 0. This is what LWJGL looks at when it actually calls the native OpenGL function. It reads that address field value and expects this to be the virtual memory address of the client memory to upload to the texture.

  2. Now, there are some OpenGL functions that will just SEGFAULT when given an invalid pointer, such as zero. However, in this case, the glTexImage2D function is actually semantically overloaded, as when it receives the zero address as the last argument, it will only allocate texture memory of the requested size (here the remaining size of the ByteBuffer) and not move any client memory to the server (i.e. the GPU).

The ByteBuffer returned by STBImage.stbi_load is direct, and hence, the correct texture memory from the client's virtual memory address space is uploaded to OpenGL.

So, in essence: When you use LWJGL, you must always only use direct NIO Buffers, not ones that are wrappers of arrays!

Upvotes: 3

Related Questions