Strange phenomenon about glDrawPixels, Any one can help me ?

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

Strange phenomenon about glDrawPixels, Any one can help me ?

george2008
Run below code, get error msg:
Caused by: java.lang.IndexOutOfBoundsException: Required 522143 remaining bytes in buffer, only had 521256
        at com.jogamp.common.nio.Buffers.rangeCheckBytes(Buffers.java:1056)
        at jogamp.opengl.gl4.GL4bcImpl.glDrawPixels(GL4bcImpl.java:5648)

------My Code---------
short[] pixels16 =  ... // generate short array data, length is 521256.  (521256 = 587*888 = 888*587).
int w = 587;
int h = 888;
BufferedImage bi = ImageDisplayUtils.createImage(w, h, pixels16);

DataBufferByte buf = (DataBufferByte)bi.getData().getDataBuffer();
byte[] bytes = buf.getData();
ByteBuffer imgBuffer = ByteBuffer.wrap(bytes);

gl.glRasterPos2f(0, 0);
gl.glDrawPixels(w, h, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE, imgBuffer);


!! BUT , if set w = 888, h = 587, everything is ok, no exception was thrown.


Any help?

Thanks in advance.
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

gouessej
Administrator
Hi

Look at the source code:
https://github.com/sgothel/gluegen/blob/master/src/java/com/jogamp/common/nio/Buffers.java#L1050

Check the size of the byte array inside DataBufferByte returned by getData().

By the way, your code seems to be inefficient, I just hope that you don't create an indirect NIO buffer at each call. You should rather find a way to reuse the data buffer as is and pass it to JOGL or create a single direct NIO buffer into which you could copy the content of the data buffer.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

george2008
>Check the size of the byte array inside DataBufferByte returned by getData().
Add one line below 'getData()', the output is correct. So the size inside DataBufferByte returned by getData() is correct.
byte[] bytes = buf.getData(); // length : w*h
System.out.println(bytes.length); // output : 521256 ( = 587*888)


>I just hope that you don't create an indirect NIO buffer at each call.
You means using 'Buffers.newDirectByteBuffer(bytes)' instead of 'ByteBuffer.wrap(bytes)' ?
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

gouessej
Administrator
There is probably a problem of alignment:
http://forum.jogamp.org/glTexImage2D-error-td4033393.html

george2008 wrote
>I just hope that you don't create an indirect NIO buffer at each call.
You means using 'Buffers.newDirectByteBuffer(bytes)' instead of 'ByteBuffer.wrap(bytes)' ?
I mean that you should create a direct NIO buffer with Buffers.newDirectByteBuffer() only once and reuse it. As you don't show a complete example, I don't really know what you do. If you create a new buffer at each call of GLEventListener.display(), you'll run out of memory.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

george2008
>There is probably a problem of alignment:
>http://forum.jogamp.org/glTexImage2D-error-td4033393.html

Do you have any plan to fix it ?
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

elect
This post was updated on .
george2008 wrote
>There is probably a problem of alignment:
>http://forum.jogamp.org/glTexImage2D-error-td4033393.html

Do you have any plan to fix it ?

It works like this, you need a buffer

(h-1) * (w + (alignemnt - w % alignment)) + w

bytes big

given:

int w = 587;
int h = 888;
alignment = 4 byte

your buffer will be

   887 * (587 + (4 - 587 % 4)) + 587 =
= 887 * (587 + 1) + 587 = 522143

bytes

This is because data gets loaded line by line based on the alignment, except the last line which seems it doesnt matter

int h = 587;
int w = 888;

works out of the box because w fits perfectly the 4 bytes alignment (888 % 4 = 0)

https://www.opengl.org/wiki/Common_Mistakes#Texture_upload_and_pixel_reads
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

gouessej
Administrator
Big kudos to elect :D We should make a small article about that for the wiki.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

elect
gouessej wrote
Big kudos to elect :D We should make a small article about that for the wiki.
Mercì, I added a small section about common OpenGL and GLSL mistakes
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

george2008
In reply to this post by elect
if set:
h = 587
w = 888
alignment = 4

using below formula, the output is '523600'
v = (h-1) * (w + (alignemnt - w % alignment)) + w
System.out.println(v);

BUT, if I use function G:Buffers.sizeof()', I got '521256', which is equal to 888*587.
int v = GLBuffers.sizeof(gl, new int[1], 1, 888, 587, 1, false);

Above two results are different,
is the formula '(h-1) * (w + (alignemnt - w % alignment)) + w'  correct ?
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

gouessej
Administrator
It's probably a rounding error, isn't it?

((h-1) * (w + (alignment - (w % alignment)))) + w

Moreover, it's up to you to pass the right size for the newly created buffer.

 ((888 - 1) * (587 + (4 - 587 % 4))) + 587 = 522143

It seems to work for me.

Are you sure that you pass the right "type" and the right "depth" to GLBuffers.sizeof()?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

elect
Yep, Gouessej is right, the modulo has the precedence
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

george2008
What is the condition determines the 'alignment' value ?
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

gouessej
Administrator
GLBuffers.sizeof() computes the bytes per pixel from the format and the type or use the value in input. Look at the implementation of this method.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

elect
In reply to this post by george2008
https://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml

Associated Gets

            glGet with argument
            GL_PACK_ALIGNMENT or GL_UNPACK_ALIGNMENT
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

Sven Gothel
Administrator
In reply to this post by gouessej
On 08/07/2015 04:25 PM, gouessej [via jogamp] wrote:
> GLBuffers.sizeof() computes the bytes per pixel from the format and the type
> or use the value in input. Look at the implementation of this method.

Yup .. this is our canonical buffer size definition/method.

~Sven


signature.asc (828 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

elect
Forgot to say, unpack is when you transfer data from cpu -> gpu, pack the other way round
Reply | Threaded
Open this post in threaded view
|

Re: Strange phenomenon about glDrawPixels, Any one can help me ?

elect
Little update, I came across this issue recently for a glTexImage3D

The same logic applies, but it is interesting to know how it works in 3 dimensions.

Supposing we have x, y and z where in general

- x is the layer (for texture arrays)

- y is the face (for cubemap textures)

- z is the level (for mipmaps)

Data will be loaded starting from the xy plane, row by row. So if we have a 4-bytes alignment, x must be aligned to this value and it must be so up to the end. This for all the xy planes on z, except the very last row on the last z.

Examples:

(3, 2, 2) requires 4 bytes for row, this means 4 bytes for the first three rows:

- ([0-3], 0, 0)

- ([0-3], 1, 0)

- ([0-3], 0, 1)

except the last one, ([0-3], 1, 1), that needs only 3

The count is 3*4+3 = 15 Bytes..

So what counts about alignment is always and only the size of the first dimension, except the last row

Let's say this is the complex way of dealing with it. The easy fix is to switch the unpack alignment to 1 byte and forget about it :D