Bug 584

Summary: Texture binding fails if image width < alignment
Product: [JogAmp] Jogl Reporter: Fabien Mars <fabmars>
Component: utilAssignee: Sven Gothel <sgothel>
Status: RESOLVED INVALID    
Severity: normal    
Priority: ---    
Version: 2   
Hardware: All   
OS: all   
Type: DEFECT SCM Refs:
Workaround: ---

Description Fabien Mars 2012-05-23 18:47:16 CEST
I'm trying to bind a .gif 2x2 texture in 4 colors, JOGL won't let me.

First loading it with BufferedImage sourceImage = ImageIO.read(url);
Then, using an appropriate Color Model: new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8, 0 }, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
I'm creating a raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 2, 2, 3, null) to hold the data
Prior to filling a new proper BufferedImage destImage = new BufferedImage(colorModel, raster, false, new Hashtable<Object, Object>());
Graphics g = destImage.getGraphics();
g.drawImage(sourceImage, 0, 0, null);
And getting the databuffer with raster.getDataBuffer().
I do the above with all my textures, no matter what they are, they will load properly. Except here:

This method is called:
      gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB, 2, 2, 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, textureBuffer);

And I get:
java.lang.IndexOutOfBoundsException: Required 14 remaining bytes in buffer, only had 12
	at com.jogamp.common.nio.Buffers.rangeCheckBytes(Buffers.java:853)
	at jogamp.opengl.gl4.GL4bcImpl.glTexImage2D(GL4bcImpl.java:25283)


That's because of what's in GLBuffers line 321: remainder won't be good if image width < alignment.

This works in C, should also in Java.
Comment 1 Fabien Mars 2012-05-24 07:33:07 CEST
Actually this very texture used to load in C and also with JOGL in 2005. I discovered this whilist dusting my code with the latest libs of everything.
Comment 2 Sven Gothel 2012-05-24 09:21:28 CEST
(In reply to comment #0)
> I'm trying to bind a .gif 2x2 texture in 4 colors, JOGL won't let me.

> 
> This method is called:
>       gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB, 2, 2, 0, GL.GL_RGB,
> GL.GL_UNSIGNED_BYTE, textureBuffer);
> 
> And I get:
> java.lang.IndexOutOfBoundsException: Required 14 remaining bytes in buffer,
> only had 12
>     at com.jogamp.common.nio.Buffers.rangeCheckBytes(Buffers.java:853)
>     at jogamp.opengl.gl4.GL4bcImpl.glTexImage2D(GL4bcImpl.java:25283)
> 
> 
> That's because of what's in GLBuffers line 321: remainder won't be good if
> image width < alignment.
> 

Alignment should be 1 or 2 in your case 
(not 4, which is the default).
It's up to you to properly set it up.

In your example, you have probably kept alignment at 4,
hence the 1st row-length is assumed to be 8:
  2 * 3 =6, aligned -> 8
the 2nd row-length is not required to be aligned,
since only the beginning of a row requires alignment:
  8 + 6 = 14

So you are missing the 2 bytes of alignment.
Either add it to the buffer, or set alignment to 1.

> This works in C, should also in Java.

Well, if the native OpenGL driver allows you to ignore alignment
and does not post an error - this is one thing.
Please notice that in such case, the OpenGL driver may
copy more bytes than you offer from host memory to GPU memory.

JOGL likes to fail-fast and  does not allow to offer less bytes
than required.

(In reply to comment #1)
> Actually this very texture used to load in C and also with JOGL in 2005. I
> discovered this whilist dusting my code with the latest libs of everything.
In 2005 we might not had this pre-validation in place
or my latest update of this code refined the restrictions.

If my calculations and/or assumptions above are wrong,
please reopen the bug and clarify.

Thank you.
Comment 3 Fabien Mars 2012-05-24 12:30:26 CEST
Indeed, I'm blatantly stupid.