My first attempt at this was to use pixel buffer objects, that is, create a sufficient large PBO, copy the texture to it using glGetTexImage, bind a new texture and copy it there using glTexImage2D. This was horribly slow, around 22ms for a 1920x1080 texture on a GeForce 88oo Ultra. I still wonder why.
Next try was to use framebuffer objects, which can be done pretty straight forward:
1 /* Assume "fbo" is a name of a FBO created using glGenFramebuffersEXT(1, &fbo),
2 * and width/height are the dimensions of the texture, respectively.
3 * "tex_src" is the name of the source texture, and
4 * "tex_dst" is the name of the destination texture, which should have been
5 * already created */
6
7 /// bind the FBO
8 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
9 /// attach the source texture to the fbo
10 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
11 GL_TEXTURE_2D, tex_src, 0);
12 /// bind the destination texture
13 glBindTexture(GL_TEXTURE_2D, tex_dst);
14 /// copy from framebuffer (here, the FBO!) to the bound texture
15 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
16 /// unbind the FBO
17 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
This works very well and very fast, less than 0.1 ms. However, you need to create a new FBO for every different texture dimensions.
Knowing this, I tried the same approach to copy a texture into a pixel buffer object, which also shows to be quite faster this way:
1 /// Again, bind fbo and attach source texture
2 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
3 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
4 GL_TEXTURE_2D, tex_src, 0);
5
6 /// read pixels into pbo from framebuffer
7 /// note you obviously need to specify a format and type
8 glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
9 glReadPixels(0,0,width,height,format,type,0);
10
11 /// unbind everything as we are done
12 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
13 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
There's of course no guarantee that these approaches are the fastest for every hardware and set-up. If you have something working faster for you, it would be nice to hear of that!