I recently encounterd a problem with ATI card: when I use PBO to upload an large image(3072 x 2048) to an 2D texture, it seems that the image has been damaged during loading. This problem will NOT happen if the image is not big enough or if I use a nVidia card. My system is windows 7 x64 and the driver is catalyst 11.8, my video card is a radeon HD 5770. The following code snippet can produce this problem:
...
QImage img("d:/big_image.png");
const unsigned int imageWidth = img.width();
const unsigned int imageHeight = img.height();
// create texture
GLuint tex = 0;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imageWidth, imageHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
// create PBO
GLuint pbo = 0;
glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
// allocate storage for PBO
glBufferData(GL_PIXEL_UNPACK_BUFFER, imageWidth * 4 * imageHeight, 0, GL_DYNAMIC_DRAW);
// map PBO
void *pboBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, imageWidth * imageHeight * 4, GL_MAP_WRITE_BIT);
if (pboBuffer) {
unsigned char *pixel = (unsigned char *)pboBuffer;
for (int i = 0; i < imageHeight; i++) {
memcpy(pixel, img.scanLine(i), img.bytesPerLine());
pixel += img.bytesPerLine();
}
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
}
// copy PBO to texture
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imageWidth, imageHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
// download texture image
glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, img.bits());
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteBuffers(1, &pbo);
glDeleteTextures(1, &tex);
img.save("d:/output.bmp");
...
The idea of code is to load an big image (a 3072 x 2048 ARGB 32bit image), create a PBO and a texture to load this image to the texture(through the PBO), and then download this texture back to host memory and save it to a image file. The newly saved image file should have the same content of the original image file, but according to my test, when the image is big enough the output image is damaged. Is anything wrong with my code or is this a driver bug?
BTW, To run this code, you have to install Qt library, but if don't have Qt, you can use whatever toolkit you like to load and store image and replace the Qt code. Both a GL2 or GL3 context can produce this problem.