I have made a test app to try PBO with mipmap. If you want test it, just compile with : g++ -o pbo main.cpp -lGL -lglut -lGLEW
(on linux system, with code inside main.cpp)
Just switch boolean variable “usePBO” to true (i.e. false) if you want to enable (i.e. disable) PBO for texture upload.
On my system, it works well without PBO and bad with PBO !
And you ?
#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <iostream>
using namespace std;
#define BUFFER_OFFSET(i) ((char*)NULL + (i))
static bool usePBO = true;
static int width = 600;
static int height = 600;
static GLuint texid;
static GLuint pboid[8];
void
idle ()
{
glutPostRedisplay ();
}
void
display ()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glBindTexture(GL_TEXTURE_2D,texid);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.f,1.f); glVertex3f(-1.f,-1.f,-1.f);
glTexCoord2f(1.f,1.f); glVertex3f(100.f,-1.f,-100.f);
glTexCoord2f(1.f,0.f); glVertex3f(100.f,1.f,-100.f);
glTexCoord2f(0.f,0.f); glVertex3f(-1.f,1.f,-1.f);
glEnd();
glutSwapBuffers ();
}
void
initGL ()
{
glewInit();
if (glewIsSupported("GL_VERSION_2_0"))
cerr << "[PBO] Ready for OpenGL 2.0" << endl;
else {
cerr << "[PBO] OpenGL 2.0 not supported" << endl;
exit(1);
}
glCullFace( GL_BACK );
glEnable( GL_DEPTH_TEST );
glEnable( GL_CULL_FACE );
glEnable( GL_TEXTURE_2D );
glDisable( GL_LIGHTING );
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0,1.0,-1.0,1.0,1.0,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void
initTextureAndShader ()
{
const int w = 256;
const int h = 256;
const int z = 5;
glGenTextures(1,&texid);
glBindTexture(GL_TEXTURE_2D,texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0.f);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float) (z-1));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, (z-1));
for ( int i = 0; i < z; ++i )
glTexImage2D(GL_TEXTURE_2D,i,GL_RGB,(w>>i),(h>>i),0,GL_RGB,GL_UNSIGNED_BYTE,0);
cerr << "Texture Allocation OK" << endl;
if ( usePBO ) {
// create PBO ...
glGenBuffers(z,pboid);
}
for ( int i = 0; i < z; ++i ) {
int iw = (w>>i);
int ih = (h>>i);
GLubyte* gputex = new GLubyte[3*iw*ih];
for ( int j = 0; j < iw*ih; ++j ) {
if ( i == 0 ) {
gputex[3*j] = 0;
gputex[3*j+1] = 255;
gputex[3*j+2] = 0;
}
else if ( i == 1 ) {
gputex[3*j] = 255;
gputex[3*j+1] = 255;
gputex[3*j+2] = 0;
}
else if ( i == 2 ) {
gputex[3*j] = 255;
gputex[3*j+1] = 0;
gputex[3*j+2] = 0;
}
else if ( i == 3 ) {
gputex[3*j] = 0;
gputex[3*j+1] = 0;
gputex[3*j+2] = 255;
}
else if ( i == 3 ) {
gputex[3*j] = 255;
gputex[3*j+1] = 255;
gputex[3*j+2] = 255;
}
}
if (! usePBO )
glTexSubImage2D( GL_TEXTURE_2D,i,0,0,iw,ih,GL_RGB,GL_UNSIGNED_BYTE,gputex);
else {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pboid[i]);
glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, 3*iw*ih, 0,
GL_STREAM_DRAW);
GLvoid* ptr1 = glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
GLubyte* tmp = (GLubyte*) ptr1;
for ( int j = 0; j < 3*iw*ih; ++j )
tmp[j] = gputex[j];
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
glTexSubImage2D( GL_TEXTURE_2D,i,0,0,iw,ih,GL_RGB,GL_UNSIGNED_BYTE,BUFFER_OFFSET(0)/*gputex*/);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
delete [] gputex;
}
if ( usePBO )
glDeleteBuffers(z,pboid);
cerr << "Texture upload OK" << endl;
}
int
main ( int argc, char** argv )
{
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize (width,height);
glutCreateWindow ("PBO");
glutIdleFunc (idle);
glutDisplayFunc (display);
initGL();
initTextureAndShader();
glutMainLoop ();
return EXIT_SUCCESS;
}