PDA

View Full Version : What does glPixelStore() do?



yj1214
08-31-2015, 04:27 PM
I'm rendering few bitmaps on the screen and without calling glPixelStore(), I get weird looking bitmaps.

This code,

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

and this code,

glPixelStorei(GL_UNPACK_ALIGNMENT, 2);

does exact same thing. What's the difference between these two codes?

hidefromkgb
08-31-2015, 04:40 PM
According to official docs (https://www.opengl.org/sdk/docs/man/html/glPixelStore.xhtml), there is no difference if your bitmaps` width is even.
TL;DR: this invocation tells OGL to assume each row of application-supplied byte data to be aligned, since aligned memory reads tend to be faster than unaligned.
1 means no alignment, 2 — each row starts at even address, 4 — each row starts at the address divisible by 4, etc…

yj1214
08-31-2015, 06:56 PM
Thanks for the answer but I still don't get it.


1 means no alignment, 2 - each row starts at even address

What is it mean by no alignment and 'each row starts at even address'?


Also, what's the difference between GL_UNPACK_ALIGNMENT and GL_PACK_ALIGNMENT?

they seems to do the same job.

GClements
08-31-2015, 08:59 PM
What is it mean by no alignment and 'each row starts at even address'?

Memory addresses are just numbers. An even address means that the address is a multiple of two.

Arrays declared as variables or allocated with e.g. malloc() or "new" can safely be assumed to be aligned to a 4-byte boundary (i.e. the address of the first byte of data in the array will be a multiple of 4). Thus you only need to concern yourself with GL_PACK_ALIGNMENT or GL_UNPACK_ALIGNMENT if the number of bytes per row isn't also a multiple of 4.



Also, what's the difference between GL_UNPACK_ALIGNMENT and GL_PACK_ALIGNMENT?

The GL_PACK_* settings affect operations which transfer data from OpenGL to the application (e.g. glReadPixels()). The GL_UNPACK_* settings affect operations which transfer data from the application to OpenGL (e.g. glTexImage2D()).

Data in application memory is considered "packed", data held within the OpenGL implementation is considered "unpacked" (i.e. where the implementation can get at it).

yj1214
08-31-2015, 11:41 PM
Ok, let me get this right.


According to this article, http://www.glprogramming.com/red/chapter08.html#name7

1. Different computers(hardwares) stores arrays in different ways such as 2 byte, 4 byte and 8 byte alignment. So to control the byte alignment, I use glPixelstore() to set the specific byte alignment.

2.

GLubyte foo[1] = {
0xc0
};


since GLubyte is an unsigned char which is only 1 byte long, I can call
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
which makes sense because my array is 1 byte long each. But this is where i'm confused.


glPixelStorei(GL_UNPACK_ALIGNMENT, 2);

How come above code works fine if unsigned char is only 1 byte long?

Or am I just completely misunderstanding something?


3. If my array was something like
unsigned long int x[] = {5, 2, 6};
then I don't need to call glPixelStorei because glPixelStorei's default value is 4...


Sorry if this is bit long.

GClements
09-01-2015, 12:22 AM
How come above code works fine if unsigned char is only 1 byte long?

Or am I just completely misunderstanding something?

Size and alignment are different things.

Suppose that you have texture data with GL_RGB format (3 bytes per component) and a width of 123, with no padding between rows (i.e. the first byte of the first pixel of one row immediately follows the last byte of the last pixel of the previous row). The stride between rows will be 3*123 = 369 bytes. Note that 369 is not a multiple of 2 or 4.

If the first row of the texture data starts at an address which is a multiple of 4, the second row won't.

If GL_UNPACK_ALIGNMENT is 4, and you try to upload the texture data with glTexImage2D(), the implementation will round the length of each row up to the next multiple of 4 (i.e. 372 bytes).

Unless you have an 8-bit CPU (and I don't think there are any 8-bit systems which support OpenGL), the CPU will typically read and write memory in "words" (typically 32 or 64 bits) rather than bytes. For this reason, it's more efficient to align data to a multiple of the word size.

Because aligning data in this way is so common, OpenGL has GL_UNPACK_ALIGNMENT and GL_PACK_ALIGNMENT, which allow you to say "if I ask you to read data, it will be aligned to a multiple of 2/4/8 bytes; if I ask you to write data, I want it aligned to a multiple of 2/4/8 bytes".



3. If my array was something like
unsigned long int x[] = {5, 2, 6};
then I don't need to call glPixelStorei because glPixelStorei's default value is 4...

The compiler will typically align x to a multiple of 4 bytes (or more), and each element will typically be either 4 or 8 bytes, so each element will be aligned to a multiple of 4 bytes (or more).

yj1214
09-01-2015, 06:14 PM
I'm sorry but I have one more question.



GLubyte foo[4] = {
0xc0, 0xc0, 0xc0, 0xc0
};

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);


This makes sense because foo is consist of 4 values which are 1 byte long each. So foo has stride of 1.



long int ham[4] = {
0xc0, 0xc0, 0xc0, 0xc0
};

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);


This makes sense because ham is consist of 4 values that are 4 bytes long each. So ham's stride is 4.



GLubyte foo[4] = {
0xc0, 0xc0, 0xc0, 0xc0
};

glPixelStorei(GL_UNPACK_ALIGNMENT, 2);


This works but i'm bit confused. Foo's stride is 1 but how come 2 works fine?


and finally,


GLubyte foo[3] = {
0xc0, 0xc0, 0xc0
};

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);


Is this valid code? thanks and again sorry for the long question...

GClements
09-01-2015, 07:03 PM
The pack/unpack alignments apply to reading and writing pixel rectangles. The spacing between rows has to be a multiple of the alignment.